1. 程式人生 > >bzoj 1030: [JSOI2007]文字生成器

bzoj 1030: [JSOI2007]文字生成器

AC自動機上跑DP 

注意的細節是fail鏈上有標記 該節點也要標記(就好比 “ ********123******** ”  索然最後沒有出現123 但是中間出現了123  這種情況不可取!) 

 

/**************************************************************
    Problem: 1030
    User: lxy8584099
    Language: C++
    Result: Accepted
    Time:132 ms
    Memory:6044 kb
***************************************************************
*/   /*     有點像 1009 TG考試 不過這個資料挺小 不用矩陣加速     我們求出不合法的個數 用總數減去就行了     一個串的時候我們用KMP轉移     因為有多個串 所以建個AC自動機 轉移     之後的就和1009一模一樣了     f[i][j]表示 表示前i個字元 目前節點為j 的不符合方案數     轉移: f[i][ c[j][k] ] += f[i-1][j] (c[j][k]不是某個認識單詞的結尾)     自動機沒有兒子自動接上fail 方便!!!     考慮到如果某節點fail鏈跳到 0 的路上也遇到標記的話         這個點也是不可取的!         處理方法:我們在自動機上用或運算。
*/ #include<queue> #include<cstdio> #include<cstring> using namespace std; const int N=1e4+50; const int MOD=10007; int c[N][26],last[N],n,m,tot; int f[105][N],ans=0,sum=1; bool vis[N]; void Add(char *s) {     int l=strlen(s),u=0;     for
(int i=0;i<l;i++)     {         int v=s[i]-'A';         if(!c[u][v]) c[u][v]=++tot;         u=c[u][v];     } vis[u]=1; } void Init() {     scanf("%d%d",&n,&m);char s[105];     for(int i=1;i<=n;i++) scanf("%s",s),Add(s); } void Ac_build() {     queue<int> q;     for(int i=0;i<26;i++)         if(c[0][i]) q.push(c[0][i]);     while(!q.empty())     {         int u=q.front();q.pop();         for(int v=0;v<26;v++)         {             if(c[u][v])             {                 last[c[u][v]]=c[last[u]][v];                 vis[c[u][v]]|=vis[c[last[u]][v]];                 // fial鏈有標記 該節點不能到達!                 q.push(c[u][v]);continue;             }             c[u][v]=c[last[u]][v]; // 這叫啥。。忘了。         }                   } } void Solve() {     f[0][0]=1;     for(int i=0;i<m;i++)         for(int u=0;u<=tot;u++)             for(int v=0;v<26;v++) if(!vis[c[u][v]])                 (f[i+1][c[u][v]]+=f[i][u])%=MOD;     for(int i=0;i<=tot;i++) (ans+=f[m][i])%=MOD;     for(int i=1;i<=m;i++) (sum*=26)%=MOD;     printf("%d\n",(sum-ans+MOD)%MOD); } int main() {     Init();     Ac_build();     Solve();     return 0; }