[置顶] ACM and String

字符串理论, 多串匹配与AC自动机

例题

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=21239#overview

A HDU 2222

木板题,统计包含个数

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
const int CHAR = 26;
const int TOTLEN = 5e5 + 9;
const int MAXLEN = 1e6 + 9;
struct Node{
    Node *fail , *next[CHAR];
    int val;
    void init(){
        fail = NULL;
        val = 0;
        memset(next , 0 , sizeof(next));
    }
};
class ACM{
public:
    void init();
    void insert(char * str);
    void build();
    int find(char * str);
private:
    Node * newnode();
    Node acm[TOTLEN];
    Node * root;
    int size;
};
Node * ACM::newnode(){
    acm[size].init();
    return &acm[size++];
}
void ACM::init(){
    size = 0;
    root = newnode();
}
void ACM::insert(char * str){
    Node * p = root;
    for ( ; *str ; ++str){
        int ch = *str - 'a';
        if (p -> next[ch] == NULL)
            p -> next[ch] = newnode();
        p = p -> next[ch];
    }
    p -> val ++;
}
void ACM::build(){
    static queue<Node *> q;
    q.push(root);
    while(!q.empty()){
        Node * tmp = q.front() ; q.pop();
        Node * p;
        for (int i = 0 ; i < CHAR ; ++i){
            Node *& now = tmp -> next[i];
            if (now != NULL){
                q.push(now);
                if (tmp == root){
                    now -> fail = root;
                    continue;
                }
                p = tmp -> fail;
                while(p != NULL){
                    if (p -> next[i] != NULL){
                        now -> fail = p -> next[i];
                        break;
                    }
                    p = p -> fail;
                }
                if (p == NULL) now -> fail = root;
            }
            else{
                if (tmp == root) now = root;
                else now = tmp -> fail -> next[i];
            }
        }
    }
}
int ACM::find(char * str){
    Node *p = root;
    int ans = 0;
    for ( ; *str ; ++str){
        int ch = *str - 'a';
        p = p -> next[ch];
        if (p == NULL)  p = root;
        Node * tmp = p;
        while(tmp != root && tmp ->val != -1){
            ans += tmp -> val;
            tmp -> val = -1;
            tmp = tmp -> fail;
        }
    }
    return ans;
}
ACM ac;
char str[MAXLEN];
void solve(){
    int n;
    scanf("%d" , &n);
    ac.init();
    while(n--){
        scanf("%s" , str);
        ac.insert(str);
    }
    ac.build();
    scanf("%s" , str);
    printf("%d\n" , ac.find(str));
}
int main(){
//    freopen("0" ,"r" ,stdin);
    int _ = 0;
    scanf("%d" , &_);
    while(_--) solve();
}

B POJ 2778

建立自动机,搞出转移矩阵,快速幂。。

% 比 - 慢多了啊!!

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>

using namespace std;

#define Rush for(int ____T , scanf("%d" , &____T); ____T--;)
#define DO(n) for ( int ____n ## __line__ = n; ____n ## __line__ -- ; )

#define ALL(A) A.begin(), A.end()
#define BSC(A, x) (lower_bound(ALL(A), x) - A.begin())
#define CTN(T, x) (T.find(x) != T.end())
#define SZ(A) int(A.size())
#define PB push_back
#define MP(A, B) make_pair(A, B)
#define fi first
#define se second

typedef long long LL;


typedef vector<int> VI;
typedef map<int, int> MII;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;



template<class T> inline void RST(T &A){memset(A, 0, sizeof(A));}
template<class T> inline void FLC(T &A, int x){memset(A, x, sizeof(A));}
template<class T> inline void CLR(T &A){A.clear();}

//}

/** Constant List .. **/ //{

const int dx4[] = {-1, 0, 1, 0};
const int dy4[] = {0, 1, 0, -1};

const int dx8[] = {-1, 0, 1, 0 , -1 , -1 , 1 , 1};
const int dy8[] = {0, 1, 0, -1 , -1 , 1 , -1 , 1};

const int dxhorse[] = {-2 , -2 , -1 , -1 , 1 , 1 , 2 , 2};
const int dyhorse[] = {1 ,  -1 , 2  , -2 , 2 ,-2 , 1 ,-1};

const int MOD = 1000000007;
//int MOD = 99990001;
const int INF = 0x3f3f3f3f;
const LL INFF = 1LL << 60;
const double EPS = 1e-9;
const double OO = 1e15;
const double PI = acos(-1.0); //M_PI;
#pragma comment(linker, "/STACK:36777216")
//}

template<class T> inline void checkMin(T &a,const T b){if (b<a) a=b;}
template<class T> inline void checkMax(T &a,const T b){if (a<b) a=b;}
//}
template<class T> inline T low_bit(T x) {return x & -x;}
/*****************************************************************/
const int CHAR = 4;
const int TOT = 129;
int next[TOT][CHAR] , fail[TOT];
bool virus[TOT];
int id[128];
const int Dic[] = {'A' , 'C' , 'G' ,'T'};
int L , root;
int newNode(){
    for (int i = 0 ; i < CHAR; ++i)
        next[L][i] = -1;
    virus[L] = 0;
    fail[L] = 0;
    return L++;
}
void init(){
    L = 0;
    root = newNode();
}
void insert(char *s){
    int now = root;
    for (int i = 0 ; s[i] ; ++i){
        int ch = id[s[i]];
        if (next[now][ch] == -1)
            next[now][ch] = newNode();
        now = next[now][ch];
    }
    virus[now] = 1;
}
void build(){
    queue<int> Q;
    for (int i = 0 ; i < CHAR ; ++i)
        if (next[root][i] == -1)
            next[root][i] = root;
        else{
            fail[next[root][i]] = root;
            Q.push(next[root][i]);
        }
    while(!Q.empty()){
        int now = Q.front();
        virus[now] |= virus[fail[now]];
        Q.pop();
        for (int i = 0 ; i < CHAR ; ++i)
            if (next[now][i] == -1)
                next[now][i] = next[fail[now]][i];
            else{
                fail[next[now][i]] = next[fail[now]][i];
                Q.push(next[now][i]);
            }
    }
}
const int MATN = 129;
const int modo = 1e5;
struct Mat{
    int Matn , Matm;
    int a[MATN][MATN];
    Mat(){
        Matn = 0;
        Matm = 0;
        memset(a , 0 , sizeof(a));
    }
    void output(){
        cout << "OUTPUT" << endl;
        for (int i = 0 ; i < Matn ; ++i){
            for (int j = 0 ; j < Matm ; ++j){
                printf("%d ",a[i][j]);
            }
            printf("\n");
        }
    }
    void init(){
        Matn = 0;Matm = 0;
        memset(a , 0 , sizeof(a));
    }
    Mat operator + (const Mat & A) const{
        Mat ret = A;
        for (int i = 0 ; i < Matn ; ++i){
            for (int j = 0 ; j < Matm ; ++j)
                ret.a[i][j] = (ret.a[i][j] + a[i][j]) % modo;
        }
        return ret;

    }
    Mat operator * (const Mat & A) const{
        Mat c ;
        c.Matn = Matn;
        c.Matm = A.Matm;
        for (int i = 0 ; i < Matn ; ++i)
            for (int j = 0 ; j < A.Matm ; ++j)
                for (int k = 0 ; k < Matm ; ++k){
                    c.a[i][j] = (c.a[i][j] + ((long long)a[i][k] * A.a[k][j])%modo);
                    if (c.a[i][j]  >= modo) c.a[i][j] -= modo;
                }
        return c;
    }
    void initI(){
        memset(a, 0 , sizeof(a));
        for (int i = 0 ; i < Matn ; ++i)
            a[i][i] = 1;
    }
    Mat power(int k){
        Mat c = *this  , b;
        b.init();
        b.Matn = Matn ; b.Matm = Matm;
        b.initI();
        while(k){
            if (k & 1)
                b = b * c;
            c = c * c;
            k >>= 1;
        }
        return b;
    }
}P , Q;
char A[15];
int n , m;

void solve(){
    init();
    DO(m){
        scanf("%s" , A);
        insert(A);
    }
    build();
    P.init();
    P.Matn = P.Matm = L;
    for (int i = 0 ; i < L ; ++i){
        if (virus[i]) continue;
        for (int j = 0  ; j < 4 ; ++j){
            int ni = next[i][j];
            if (ni == -1) ni = root;
//            assert(ni != -1);
            if (virus[ni]) continue;
            P.a[i][ni]++;
        }
    }
//    P.output();
    P = P.power(n);
//    P.output();
    Q.init();
    Q.Matn = 1 , Q.Matm = L;
    Q.a[0][0] = 1;
//    for(int i = 0 ; i < L ; ++i) Q.a[0][i] = 1;
    Q = Q * P;
//    Q.output();
    int ans = 0;
    for (int i = 0 ; i < L ; ++i) if (!virus[i]){
        ans = (ans + Q.a[0][i]);
        if (ans >= modo) ans -= modo;
    }
    printf("%d\n" , ans);
}
int main(){
    id['A'] = 0;
    id['C'] = 1;
    id['G'] = 2;
    id['T'] = 3;
    while(~scanf("%d%d" , &m , &n))solve();
}




Manecher

资料

http://blog.csdn.net/ggggiqnypgjg/article/details/6645824

例题

http://acm.hdu.edu.cn/showproblem.php?pid=3068

http://poj.org/problem?id=3974

http://acmpj.zstu.edu.cn/JudgeOnline/showproblem?problem_id=3780

http://acmpj.zstu.edu.cn/JudgeOnline/showproblem?problem_id=3769

木板

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 120000;
namespace Manacher_String{
char Ma[N << 1];
int rad[N << 1] , ml;
void Manacher(char *s , int len){
    int l = 0;
    Ma[ l ++ ] = '.';
    Ma[ l ++ ] = ',';
    for (int i = 0 ; i < len ; ++i){
        Ma[ l ++ ] = s[i];
        Ma[ l ++ ] = ',';
    }
    Ma[l] = 0;
    int pnow = 0 , pid = 0;
    for (int i = 1 ; i < l ; ++i){
        if (pnow > i)
            rad[i] = min(rad[(pid << 1) - i] , pnow - i);
        else
            rad[i] = 1;
        for ( ; Ma[i - rad[i]] == Ma[i + rad[i]] ; rad[i] ++);
        if (i + rad[i] > pnow){
            pnow = i + rad[i];
            pid = i;
        }
    }
    ml = l;
}
}using namespace Manacher_String;
char s[N];
int main(){
    while(~scanf("%s" , s)){
        int n = strlen(s);
        Manacher(s , n);
        int ans = 0;
        for (int i = 1 ; i < ml ; ++i){
            ans = max(ans , rad[i] - 1);
        }
        printf("%d\n" , ans);
    }
}

http://acm.hdu.edu.cn/showproblem.php?pid=3948

hash 一下即可



http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=12581#problem/A
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3661

你可能感兴趣的:([置顶] ACM and String)