ac自动机小结

1.hdu3247

用ac自动机预处理出所有文本串到文本串的安全距离(即不通过病毒串)

说下为什么不加bfs部分的注释部分,因为他会导致所求的距离不是安全距离,而之所以能保证bfs的正确是因为如果两文本串连接会通过病毒部分的话,那么next一定会先到病毒部分,(因为病毒部分一定是在两个文本串之间会导致next一定优先指向病毒串)比如当前串遍历完了接下来会有01两种选择,如果走零一定会走到病毒串,那就得老老实实走1.

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
const int maxa = 60000;
const int cha = 2;
int dp[10][1024];
int dis[10][maxa];
int point[10];
int n, m, k;
int leng[10];
struct Tire{
    int next[maxa][cha], fail[maxa], end[maxa];
    int root, L;
    int newnode(){
        for(int i = 0; i < cha; i++){
            next[L][i] = -1;
        }
        end[L++] = 0;
        return L-1;
    }
    void init(){
        L = 0;
        root = newnode();
    }
    int insert(char buf[], int ii){
        int len = strlen(buf);
        int now = root;
        for(int i = 0; i < len; i++){
            int x = buf[i] -'0';
            if(next[now][x] == -1)
                next[now][x] = newnode();
            now = next[now][x];
            //printf("%d ", now);
        }//puts("");
        end[now] = ii;
        return now;
    }
    void build(){//printf("build
");
        queue<int>Q;
        fail[root] = root;
        for(int i = 0; i < cha; 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();
            Q.pop();
            end[now] |= end[fail[now]];
            for(int i = 0; i < cha; 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]);
                   // printf("**%d %d
",next[now][i],next[fail[now]][i]);
                }
            }
        }
    }
    void bfs(int ii){//printf("bfs
");
        queue<int> que;
        int vis[maxa];
        memset(vis, 0, sizeof(vis));
        que.push(point[ii]);
        vis[0] = 1;
        dis[ii][point[ii]] = 0;
        while(!que.empty()){
            int now = que.front(); que.pop();//printf("%d %d
", dis[ii][now], now);
            for(int i =0; i < 2; i++){
                int Next = next[now][i];
                if(vis[Next] == 0 && end[Next] != -1){
                    dis[ii][Next] = dis[ii][now] +1;
                    vis[Next] = 1;
                    que.push(Next);
                }
                /*Next = fail[Next];
                while(Next){
                    if(vis[Next] == 0 && end[Next] != -1){
                        dis[ii][Next] = dis[ii][now] +1;
                        vis[Next] = 1;
                        que.push(Next);
                    }
                    Next = fail[Next];
                }*/
            }
        }
    }
    int solve(){
        memset(dis, -1, sizeof(dis));
        for(int i = 0;i < n; i++){
            bfs(i);
        }//printf("solve%d %d
", dis[0][point[1]], dis[1][point[0]]);//printf("%d %d
", point[0], point[1]);
        for(int i =0 ;i  < n; i++){
            for(int k = 0; k < (1<<n); k++){
                dp[i][k] = 10000000;
            }
        }
        for(int i = 0; i < n; i++){
            dp[i][(1<<i)] = leng[i];
        }
        for(int i =1 ;i < n; i++){
            for(int k = 0; k < n; k++){
                for(int j = 0; j < (1<<n); j++){
                    if(dp[k][j] < 10000000){
                        for(int h = 0; h < n; h++){
                            if(!(j&(1<<h)) && dp[k][j]!=-1){
                                dp[h][j|(1<<h)] = min(dp[h][j|(1<<h)], dp[k][j] + dis[k][point[h]]);
                            }
                        }
                    }
                }
            }
        }
        int ans = 10000000;
        for(int i = 0; i < n; i++){
            ans = min(ans, dp[i][(1<<n)-1]);
        }
        return ans;
    }
};
char buf[1000005];
Tire ac;
int main(){
    int m;
    while(scanf("%d%d", &n, &m), n+m){
        ac.init();
        for(int i =0 ;i  < n; i++){
            scanf("%s", buf);
            leng[i] = strlen(buf);
            point[i]=ac.insert(buf, 1+i);
        }
        for(int i =0; i < m; i++){
            scanf("%s", buf);
            ac.insert(buf, -1);
        }
        ac.build();
        printf("%d
", ac.solve());
    }
}
/*
abcdefg
bcdefg
cdef
de
e
ssaabcdefg


*/
View Code

2.poj3341

ac自动机加状压dp加广搜优化

#include<iostream>
#include<map>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
const int maxa = 500;
const int cha = 4;
int n, m, k;
int num_[4];
map<char, int> mp;
/*struct point{
    short a[4];
    bool operator <(const point& b)const{
        if(a[0] != b.a[0]) return a[0] < b.a[0];
        else if(a[1] != b.a[1]) return a[1] < b.a[1];
        else if(a[2] != b.a[2]) return a[2] < b.a[2];
        else return a[3] < b.a[3];
    }
};
map<point, int>dp[maxa];
map<point, bool> bo;*/
int dp[500][11*11*11*11];
int num[maxa];
struct Tire{
    int next[maxa][cha], fail[maxa];
    long long end[maxa], po[maxa];
    int root, L;
    int newnode(){
        for(int i = 0; i < cha; i++){
            next[L][i] = -1;
        }
        end[L] = 0;
        num[L++] = 0;
        return L-1;
    }
    void init(){
        L = 0;
        root = newnode();
    }
    void insert(char buf[], int ii){
        int len = strlen(buf);
        int now = root;
        for(int i = 0; i < len; i++){
            int x = mp[buf[i]];
            if(next[now][x] == -1)
                next[now][x] = newnode();
            now = next[now][x];
            //printf("%d ", now);
        }//puts("");
        long long one = 1;
        end[now] |= (one<<ii);
    }
    void build(){
        queue<int>Q;
        fail[root] = root;
        for(int i = 0; i < cha; i++){
            if(next[root][i] == -1)
                next[root][i] = root;
            else{
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        }
        while(!Q.empty()){//printf("*");
            int now = Q.front();
            end[now] |= end[fail[now]];
            long long p = end[now];
            while(p){
                num[now] += p%2;
                p /= 2;
            }
            Q.pop();
           // end[now] |= end[fail[now]];
            for(int i = 0; i < cha; 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]);
                   // printf("**%d %d
",next[now][i],next[fail[    now]][i]);
                }
            }
        }
    }
    int solve(){//printf("**%d
", next[1][3]);
        memset(dp, -1, sizeof(dp));
        dp[0][0] = 0;
        bool vis[11*11*11*11];
        memset(vis, 0, sizeof(vis));
        queue<int>que;
        que.push(0);
        while(!que.empty()){
            int now = que.front(); que.pop();
            //printf("%d ", now);
            int wei = 1;
            for(int i =0;i < 4; i++){/*if(now==1){printf("&&
");
                    printf("%d %d
", wei, num_[i]);
                }*/
                if(now % (wei*(num_[i]+1)) /wei == num_[i]){
                    wei *= num_[i] +1;
                    continue;
                }
                int Next_state = now+wei;
                if(!vis[Next_state]){
                    vis[Next_state] = 1;
                    que.push(Next_state);
                }
                for(int k = 0; k < L; k++){
                    /*if(k == 1 && now == 1){
                        printf("--%d %d
", next[k][i],Next_state);
                    }*/
                    if(dp[k][now] == -1)continue;
                    dp[next[k][i]][Next_state] = max(dp[next[k][i]][Next_state], dp[k][now]+num[next[k][i]]);
                }
                wei *= (num_[i]+1);
            }
        }
        int ans = 0;
        int maxn = 1;
        for(int i = 0;i < 4; i++){
            maxn *= num_[i]+1;
        }
            for(int k = 0; k < maxn; k++){
        for(int i = 0; i < L; i++){//printf("%d %d %d
", i, k, dp[i][k]);
                ans = max(ans, dp[i][k]);
            }
        }return ans;
    }
};
char buf[45];
Tire ac;
int main(){
    //freopen("in.cpp","r", stdin);
    mp['A'] = 0;
    mp['T'] = 1;
    mp['G'] = 2;
    mp['C'] = 3;
    int n;
    int Case = 1;
    while(scanf("%d", &n), n != 0){
        memset(num_, 0, sizeof(num_));
        ac.init();
        for(int i = 0; i < n; i++){
            scanf("%s", buf);
            ac.insert(buf, i);
        }
        scanf("%s", buf);
        memset(num, 0, sizeof(num));
        for(int i = 0; buf[i]; i++){
            num_[mp[buf[i]]] ++;
        }
        ac.build();
        printf("Case %d: %d
", Case ++, ac.solve());
    }
}
/*
abcdefg
bcdefg
cdef
de
e
ssaabcdefg


*/
View Code

3.poj2778

题意,给出一些串,问m个字符组成的串不包含这些串的有多少种情况。

自动机加矩阵快速幂。

矩阵相乘就是第i行第j列的数就是前一个矩阵的第i行,与后一矩阵的第j列,要保证前一个矩阵的列数等于后一个矩阵的行数。

构造的时候,只要把那些通向结点或通向的点的fild指向结点的节点去掉,其他正常

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
const int maxa = 105;
const int cha = 4;
#define LL long long
int n, m, k;
map<char, int> mp;
const int mod = 100000;
struct Matrix{
    int a[maxa][maxa];
    Matrix(){
        memset(a, 0, sizeof(a));
    }
    Matrix operator *(const Matrix &b)const
    {
        Matrix ret;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                for(int k=0;k<n;k++)
                {
                    int tmp=(long long)a[i][k]*b.a[k][j]%mod;
                    ret.a[i][j]=(ret.a[i][j]+tmp)%mod;
                }
        return ret;
    }/*
    Matrix operator *(const Matrix &b) const{
        Matrix tmp;
        for(int i =0 ;i < n; i++){;
            for(int j = 0; j < n; j++){
                for(int k = 0;k  <n; k++){
                    LL lo = (LL) (tmp.a[i][j]) + (LL)(a[i][k]) *b.a[k][j];
                    lo %= mod;
                    tmp.a[i][j] = lo;
                }
            }
        }
        return tmp;
    }*/
};
struct Tire{
    int next[maxa][cha], fail[maxa], end[maxa];
    int root, L;
    int newnode(){
        for(int i = 0; i < cha; i++){
            next[L][i] = -1;
        }
        end[L++] = 0;
        return L-1;
    }
    void init(){
        L = 0;
        root = newnode();
    }
    void insert(char buf[]){
        int len = strlen(buf);
        int now = root;
        for(int i = 0; i < len; i++){
            int x = mp[buf[i]];
            if(next[now][x] == -1)
                next[now][x] = newnode();
            now = next[now][x];
            //printf("%d ", now);
        }//puts("");
        end[now] ++;
    }
    void build(){
        queue<int>Q;
        fail[root] = root;
        for(int i = 0; i < cha; 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();
            if(end[fail[now]]){
                end[now] = 1;
            }
            Q.pop();
           // end[now] |= end[fail[now]];
            for(int i = 0; i < cha; 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]);
                   // printf("**%d %d
",next[now][i],next[fail[now]][i]);
                }
            }
        }
    }
    Matrix make_Maxtrix(){
        Matrix tmp;
        for(int i = 0; i < L; i++){
            for(int k = 0; k < cha; k++){
                if(!end[next[i][k]]){
                    tmp.a[i][next[i][k]] ++;
                }
            }
        }
        return tmp;
    }
};
Matrix pow(Matrix a,int m)
{
    Matrix ret;// = Matrix(a.n);
    for(int i = 0; i < n; i++)
        ret.a[i][i]=1;
    Matrix tmp=a;
    while(m)
    {
        if(m&1)ret=ret*tmp;
        tmp=tmp*tmp;
        m>>=1;
    }
    return ret;
}
char buf[1000005];
Tire ac;
int main(){

mp['A'] = 0;
mp['T'] = 1;
mp['G'] = 2;
mp['C'] = 3;
    int N, M;
    while(scanf("%d%d", &N, &M)!=EOF){
        ac.init();
        while(N--){
            scanf("%s", buf);
            ac.insert(buf);
        }
        ac.build();
        n =  ac.L;
        Matrix a = ac.make_Maxtrix();
        Matrix b = pow(a, M);;
        int ans =0 ;
        for(int i = 0; i < n ;i++){
            ans += b.a[0][i];
            ans %= mod;
        }printf("%d
", ans);
    }
}
/*
abcdefg
bcdefg
cdef
de
e
ssaabcdefg


*/
View Code

4.ZOJ 3494 BCD Code(AC自动机+数位DP)

题目:给出一些模式串,给出一个范围[A,B],求出区间内有多少个数,写成BCD之后,不包含模式串

数位dp加ac自动机

#include<string.h>
#include<queue>
#include<stdio.h>
#include<iostream>
using namespace std;
const long long maxa = 2005;
const long long cha = 2;
const long long mod = 1000000009;
struct Tire{
    long long next[maxa][cha], fail[maxa], end[maxa];
    long long root, L;
    long long newnode(){
        for(long long i = 0; i < cha; i++){
            next[L][i] = -1;
        }
        end[L++] = 0;
        return L-1;
    }
    void init(){
        L = 0;
        root = newnode();
    }
    void insert(char buf[]){
        long long len = strlen(buf);
        long long now = root;
        for(long long i = 0; i < len; i++){
            long long x = buf[i] - '0';
            if(next[now][x] == -1){
                next[now][x] = newnode();
            }
            now = next[now][x];
        }end[now] = 1;
    }
    void build(){
        queue<int> Q;
        fail[root] = root;
        for(long long i = 0;i < cha; i++){
            if(next[root][i] == -1){
                next[root][i] = root;
            }else{
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        }
        while(!Q.empty()){
            long long now = Q.front();Q.pop();
            if(end[fail[now]])end[now] = 1;
            for(long long i = 0; i < cha; 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]);
                }
            }
        }
    }
}ac;
/*
struct Trie
{
    int next[2010][2],fail[2010];
    bool end[2010];
    int root,L;
    int newnode()
    {
        for(int i = 0;i < 2;i++)
            next[L][i] = -1;
        end[L++] = false;
        return L-1;
    }
    void init()
    {
        L = 0;
        root = newnode();
    }
    void insert(char buf[])
    {
        int len = strlen(buf);
        int now = root;
        for(int i = 0;i < len ;i++)
        {
            if(next[now][buf[i]-'0'] == -1)
                next[now][buf[i]-'0'] = newnode();
            now = next[now][buf[i]-'0'];
        }
        end[now] = true;
    }
    void build()
    {
        queue<int>Q;
        fail[root] = root;
        for(int i = 0;i < 2;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();
            Q.pop();
            if(end[fail[now]])end[now] = true;
            for(int i = 0;i < 2;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]);
                }
        }
    }
};
Trie ac;
*/
//位数,节点,是否含有,是否有前导零
long long dp[205][maxa][2][2];
long long Next[maxa][10][2];
void NEXT(long long now, long long kk){
    long long ok = 0;
    long long ii = now;
    for(long long i= 3; i >= 0; i--){
        ii = ac.next[ii][((1<<i)&kk)?1:0];
        if(ac.end[ii]) ok = 1;
    }
    Next[now][kk][0] = ii;
    Next[now][kk][1] = ok;
}

long long init(){
    memset(dp, -1, sizeof(dp));
    for(long long i = 0;i < ac.L; i++){
        for(long long k = 0;k < 10; k ++){
            NEXT(i, k);
        }
    }
}
long long num[maxa];
long long dfs(long long pos, bool limit, bool yes, long long node, bool isZero){
    if(pos == 0){
        return yes^1;
    }
    if(!limit && isZero == 0 && dp[pos][node][yes][isZero]!=-1)
        return dp[pos][node][yes][isZero];
    long long nn = limit? num[pos]:9;
    long long res = 0;
    for(long long i = 0; i <= nn; i++){
        if(isZero&& i == 0)
            res += dfs(pos-1, limit&&i==nn, yes, node, isZero);
        else
            res += dfs(pos-1, limit &&(i == nn), Next[node][i][1]|yes, Next[node][i][0], 0);
        res %= mod;
    }
    if(!limit){
        dp[pos][node][yes][isZero] = res;
    }
    return res;
}
long long ans(char *a){
    long long l = strlen(a);
    for(long long i = 0; i < l ; i++){
        num[l-i] = a[i]-'0';
    }
    return dfs(l, 1, 0, 0, 1);
}
void a_1(char *a){
    int l = strlen(a);
    for(int i = l-1; i>= 0; i--){
        if(a[i] == '0'){
            a[i] = '9';
        }else{
            a[i] --;break;
        }
    }
}
char buf[maxa], buf1[maxa];
int main(){
    long long t;
    cin>>t;
    while(t--){
        ac.init();
        long long n;
        cin>>n;
        while(n--){
            scanf("%s", buf);
            ac.insert(buf);
        }//printf("*");
        ac.build();
        init();
        scanf("%s%s", buf, buf1);
        a_1(buf);
        cout<<(mod+ans(buf1)- ans(buf))%mod<<endl;
        //printf("%d
", (mod+ans(buf1)- ans(buf))%mod);
    }
}
/*
999992719
4
1
0
1 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0
1 10000000000000000000000000000
3
00
0101011
0100000
1 10000000000000000000000000000
5
01010101
010001000010
010100000000100
01010011111111111
0101010100001111111
1 10000000000000000000000000000000000000000000000000000000000000000000000000000000000
805306365
426375876
*/
View Code

 5.LightOJ 1427

题目大意:给一个长度小于10^6的字符串以及小于500个长度小于500的字符串,问每个字符串在大字符串中出现的次数。

基础ac自动机问题,对模板做一些小修改就可以了。需要注意的是字符串有可能重复

这是比较裸的思路,他的时间主要取决于主串的长度

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
const int maxa = 500000;
const int cha = 26;
int n, m, k;
int ans[505];
struct Tire{
    int next[maxa][cha], fail[maxa], end[maxa];
    int root, L;
    int newnode(){
        for(int i = 0; i < cha; i++){
            next[L][i] = -1;
        }
        end[L++] = 0;
        return L-1;
    }
    void init(){
        L = 0;
        root = newnode();
    }
    void insert(char buf[], int ii){
        int len = strlen(buf);
        int now = root;
        for(int i = 0; i < len; i++){
            if(next[now][buf[i] - 'a'] == -1)
                next[now][buf[i]-'a'] = newnode();
            now = next[now][buf[i]-'a'];
            //printf("%d ", now);
        }//puts("");
        ans[ii] = now;
    }
    void build(){
        queue<int>Q;
        fail[root] = root;
        for(int i = 0; i < cha; 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();
            Q.pop();
           // end[now] |= end[fail[now]];
            for(int i = 0; i < cha; 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]);
                   // printf("**%d %d
",next[now][i],next[fail[now]][i]);
                }
            }
        }
    }
    void solve(char *s){
        //memset(ans, 0, sizeof(ans));
        int k = 0;
        for(int i = 0; s[i]; i++){
            int t = s[i] - 'a';
            k = next[k][t];
            int j = k;
            while(j){
                end[j]++;
                j = fail[j];
            }//puts("");
        }
        return ;
    }
};
char buf[1000005], buf1[1000005];
Tire ac;
int main(){
    int t, n;
    scanf("%d", &t);
    for(int cas = 1; cas <= t; cas++){
        scanf("%d", &n);
        ac.init();
        //memset(ac.end, 0, sizeof(ac.end));
        scanf("%s", buf1);
        for(int i = 0; i < n; i++){
            scanf("%s", buf);
            ac.insert(buf, i+1);
        }
        ac.build();
        ac.solve(buf1);
        printf("Case %d:
", cas);
        for(int i = 1; i <= n; i++){
            printf("%d
", ac.end[ans[i]]);
        }
    }
}
/*
abcdefg
bcdefg
cdef
de
e
ssaabcdefg


*/
View Code

这是改进过的,时间取决于树的规模,只考虑solve的过场的话时间至少优化掉四倍,从最终跑的时间来看也是这样的。

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
const int maxa = 500000;
const int cha = 26;
int n, m, k;
int ans[505];
struct Tire{
    int next[maxa][cha], fail[maxa], end[maxa];
    int qq[maxa];
    int pos[maxa], tt;
    int root, L;
    int newnode(){
        for(int i = 0; i < cha; i++){
            next[L][i] = -1;
        }
        end[L++] = 0;
        return L-1;
    }
    void init(){
        tt = 0;
        L = 0;
        root = newnode();
    }
    void insert(char buf[], int ii){
        int len = strlen(buf);
        int now = root;
        for(int i = 0; i < len; i++){
            if(next[now][buf[i] - 'a'] == -1)
                next[now][buf[i]-'a'] = newnode();
            now = next[now][buf[i]-'a'];
            //printf("%d ", now);
        }//puts("");
        pos[ii] = now;
    }
    void build(){
        queue<int>Q;
        fail[root] = root;
        for(int i = 0; i < cha; i++){
            if(next[root][i] == -1)
                next[root][i] = root;
            else{
                qq[tt++] = next[root][i];
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        }
        while(!Q.empty()){
            int now = Q.front();
            Q.pop();
           // end[now] |= end[fail[now]];
            for(int i = 0; i < cha; i++){
                if(next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else{
                    qq[tt++] = next[now][i];
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                   // printf("**%d %d
",next[now][i],next[fail[now]][i]);
                }
            }
        }
    }
    void solve(char *s, int n){
        memset(ans, 0, sizeof(ans));
        int k = 0;
        for(int i = 0; s[i]; i++){
            int t = s[i] - 'a';
            k = next[k][t];
            end[k] ++;
        }
        for(int i = tt-1; i >= 0; i--){
            int j = qq[i];
                end[fail[j]] += end[j];
        }
        /*printf("*");
        for(int i = 0; i < L; i++){
            printf("%d ", end[i]);
        }puts("");*/
        for(int i = 1; i <= n; i++){
            printf("%d
", end[pos[i]]);
        }
        return ;
    }
};
char buf[1000005], buf1[1000005];
Tire ac;
int main(){
    int t, n;
    scanf("%d", &t);
    for(int cas = 1; cas <= t; cas++){
        scanf("%d", &n);
        ac.init();
        //memset(ac.end, 0, sizeof(ac.end));
        scanf("%s", buf1);
        for(int i = 0; i < n; i++){
            scanf("%s", buf);
            ac.insert(buf, i+1);
        }
        ac.build();
        printf("Case %d:
", cas);
        ac.solve(buf1, n);
    }
}
/*
abcdefg
bcdefg
cdef
de
e
ssaabcdefg


*/
View Code

6.hdu2243

自动机加矩阵快速幂,和poj2778一样的解法,先求不能组成的在用所有能组成的情况减去,注意的是幂数在int以内,不知道为什么我按long long 输入然后加1就T掉了

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int maxa = 50;
const int cha = 26;
int L;
struct Matrix{
    unsigned long long a[maxa][maxa];
    Matrix(){
        memset(a, 0, sizeof(a));
    }
    Matrix operator *(const Matrix &b)const{
        Matrix ret;
        for(int i = 0;i < L; i++){
            for(int j = 0; j < L; j++){
                for(int k = 0; k < L; k++){
                    ret.a[i][j] = (ret.a[i][j] + a[i][k] * b.a[k][j]);
                }
            }
        }
        return ret;
    }
};
Matrix pow(Matrix a, long long m){
    Matrix ret;
    for(int i = 0;i < L; i++){
        ret.a[i][i] = 1;
    }
    Matrix tmp = a;
    while(m){
        if(m & 1)
            ret = ret * tmp;
        tmp = tmp * tmp;
        m >>= 1;
    }
    return ret;
}
struct tire{
    int next[maxa][cha], fail[maxa], end[maxa];
    int root;
    int newnode(){
        for(int i = 0; i < cha; i++){
            next[L][i] = -1;
        }
        end[L ++] = 0;
        return L - 1;
    }
    void init(){
        L = 0;
        root = newnode();
    }
    int insert(char buf[]){
        int len = strlen(buf);
        int now = root;
        for(int i = 0; i < len; i++){
            int x = buf[i] - 'a';
            if(next[now][x] == -1){
                next[now][x] = newnode();
            }
            now = next[now][x];
        }
        end[now] = 1;
        return now;
    }
    void build(){
        queue<int>Q;
        fail[root] = root;
        for(int i =0 ; i < cha ; 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();
            if(end[fail[now]]){
                end[now] = 1;
            }
            Q.pop();
            for(int i =0 ;i < cha; 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]);
                }
            }
        }
    }
    void make(int m){
        Matrix aa;
        for(int i =0; i < L;i ++){
            if(end[i] == 0)
                for(int k = 0;k  < cha; k++){
                    int nxt = next[i][k];
                    if(end[nxt] == 0)
                        aa.a[nxt][i] ++;
                }
        }
        for(int i = 0;i < L; i++){
            if(end[i] == 0)
            aa.a[L][i] = 1;
        }
        aa.a[L][L] = 1;
        /*for(int i = 0;i <= L; i++){
            for(int k = 0; k <= L; k++){
                cout<<aa.a[i][k]<< " ";
            }
            cout<<endl;
        }*/
        aa.a[L][0] = 1;
        L ++;
        aa = aa*pow(aa, m);
        int LL = L;
        Matrix b;
        b.a[0][0] = 26;
        b.a[0][1] = 0;
        b.a[1][0] = 1;
        b.a[1][1] = 1;
        L = 2;
        b = b*pow(b, m);
        //cout<<b.a[1][0]<<" "<<aa.a[LL - 1][0]<<endl;;
        cout<<b.a[1][0] - aa.a[LL-1][0]<<endl;;
    }
}ac;
char buf[100];
int main(){
    int n;
    int m;
    while(scanf("%d%d", &n, &m)!=EOF){
        ac.init();
        for(int i =0 ;i  < n; i++){
            scanf("%s", buf);
            ac.insert(buf);
        }
        ac.build();
        ac.make(m);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/icodefive/p/4451679.html