bzoj 1030 文本生成器

貌似是AC自动机模板题,,,我却又调了两天我的天啊啊啊啊啊,,,这还怎么省选还是保龄吧,,比起Shallwe我的马力实在是醉了,,,我要马力!!!我还要马里奥!
知识点:1.AC自动机以0为根节点即可 2.get_fail实现利用BFS
3.这个题很重要的一点是上传标记,就是对于fail指向的如果是danger的那么这个节点也是danger的我一开始忘记了这关键的一点所以一直错错错,,4.bfs时特判下0拓展出的节点
剩下的就交个dp了,,,

#include<iostream> 
#include<cstring> 
#include<string> 
#include<cstdio> 
#include<queue>
#define P 10007 
#define N 100 
using namespace std; 
struct trie{ bool judge; int a[26]; int fail;}; 
trie T[6500]; 
int n,m,cnt,f[2][6500],g[6500][26],i,j,k;
char s[65][N+5]; 
inline int getnum(){
    char c; int num;
    while (!isdigit(c = getchar()));
    num = c - '0';
    while (isdigit(c = getchar())) num =  num*10 +c -'0';
    return num;
}

void init(){ 
    n = getnum(); m = getnum();
    for (int i = 1; i<= n;++i) scanf("%s",s[i]+1); 
    memset(T,0,sizeof(T));
} 

inline void make_trie(char s0[]){ 
    int q = 0, l = strlen(s0+1); 
    for (int i = 1;i <= l; ++i){ 
        int k = s0[i] - 65; 
        if (!T[q].a[k]) T[q].a[k] = ++cnt; 
        q = T[q].a[k]; 
    } 
    T[q].judge = 1; 
} 

void get_fail(){ 
    queue<int>Q; int t;
    Q.push(0); 
    while (!Q.empty()){ 
        int x = Q.front(); Q.pop(); 
            for (int i = 0;i < 26;++i)
              if (T[x].a[i]){ 
               t = T[x].fail; 
               while (t&&!T[t].a[i]) t = T[t].fail; 
        t = T[t].a[i];
        if (x) T[T[x].a[i]].fail = t; 
        Q.push(T[x].a[i]);
        T[T[x].a[i]].judge |= T[t].judge;
        } 
    }  
} 

void make_ac(){ 
    cnt = 0; 
    for (int i = 1;i <= n; ++i) make_trie(s[i]); 
    get_fail(); 
} 

void dp(){ 
    int ans = 1; bool x = 0;
    memset(g,0xff,sizeof(g));
    memset(f,0,sizeof(f));
    for (int i = 0;i <= cnt; ++i)
      if (!T[i].judge)
        for (int j = 0;j < 26; ++j) { 
        int q = i;  
        while (q&&!T[q].a[j]) q = T[q].fail;
        q = T[q].a[j];
        if (!T[q].judge) g[i][j] = q;}
    for (int i = 1;i <= m;++i) ans = ans*26%P;
    f[0][0] = 1;
    for (int k = 1;k <= m;++k){
        memset(f[x^1],0,sizeof(f[x^1]));
    for (int i = 0;i <= cnt; ++i)
      if (!T[i].judge)
      { 
      for (int j = 0;j < 26;++j)
        if (g[i][j]>=0) f[x^1][g[i][j]] =(f[x^1][g[i][j]]+f[x][i])%P;}
    x^=1;
    }
    for (int i = 0; i<=cnt;++i)
      if (!T[i].judge) {
      ans = ans-f[x][i];
      if (ans<0) ans+=P;}
      cout<<ans<<endl;
} 

int main(){ 
    init(); 
    make_ac(); 
    dp(); 
    return 0; 
}

你可能感兴趣的:(bzoj 1030 文本生成器)