1. 程式人生 > >[JSOI2007]文本生成器

[JSOI2007]文本生成器

生成 pac ron scan [] 只需要 描述 val fail

題目描述

JSOI交給隊員ZYX一個任務,編制一個稱之為“文本生成器”的電腦軟件:該軟件的使用者是一些低幼人群,他們現在使用的是GW文本生成器v6版。

該軟件可以隨機生成一些文章―――總是生成一篇長度固定且完全隨機的文章—— 也就是說,生成的文章中每個字節都是完全隨機的。如果一篇文章中至少包含使用者們了解的一個單詞,那麽我們說這篇文章是可讀的(我們稱文章a包含單詞b,當且僅當單詞b是文章a的子串)。但是,即使按照這樣的標準,使用者現在使用的GW文本生成器v6版所生成的文章也是幾乎完全不可讀的?。ZYX需要指出GW文本生成器 v6

生成的所有文本中可讀文本的數量,以便能夠成功獲得v7更新版。你能幫助嗎?

輸入輸出格式

輸入格式:

輸入文件的第一行包含兩個正整數,分別是使用者了解的單詞總數N (<= 60),GW文本生成器 v6生成的文本固定長度M;以下N行,每一行包含一個使用者了解的單詞。這裏所有單詞及文本的長度不會超過100,並且只可能包含英文大寫字母A..Z

輸出格式:

一個整數,表示可能的文章總數。只需要知道結果模10007的值。

輸入輸出樣例

輸入樣例#1: 復制
2 2
A
B
輸出樣例#1: 復制
100
令f[i][j]表示文章長度為i,在AC自動機位置為j沒有單詞的方案數
然後答案就是26m-∑f[m][]
轉移就是從AC自動機往下走
f[i+1][ch[j][k]]+=f[i][j] (ch[j][k]位置沒有標記)
註意處理AC自動機時,處理包含的情況
val[x]|=val[fail[x]]
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 queue<int>Q;
 9 int ch[10010][27],f[110][10010],size,val[10010],fail[10010
],n,m,Mod=10007,ans; 10 char s[110]; 11 int qpow(int x,int y) 12 { 13 int res=1; 14 while (y) 15 { 16 if (y&1) res=1ll*res*x%Mod; 17 x=1ll*x*x%Mod; 18 y>>=1; 19 } 20 return res; 21 } 22 void insert(int len) 23 {int i; 24 int now=0; 25 for (i=0;i<len;i++) 26 { 27 if (ch[now][s[i]-A]==0) 28 ch[now][s[i]-A]=++size; 29 now=ch[now][s[i]-A]; 30 } 31 val[now]=1; 32 } 33 void AC_build() 34 {int i; 35 for (i=0;i<26;i++) 36 if (ch[0][i]) 37 fail[ch[0][i]]=0,Q.push(ch[0][i]); 38 while (Q.empty()==0) 39 { 40 int u=Q.front(); 41 Q.pop(); 42 for (i=0;i<26;i++) 43 { 44 if (ch[u][i]) fail[ch[u][i]]=ch[fail[u]][i],Q.push(ch[u][i]); 45 else ch[u][i]=ch[fail[u]][i]; 46 if (val[fail[u]]) 47 val[u]=val[fail[u]]; 48 } 49 } 50 } 51 int main() 52 {int i,j,k,len; 53 cin>>n>>m; 54 for (i=1;i<=n;i++) 55 { 56 scanf("%s",s); 57 len=strlen(s); 58 insert(len); 59 } 60 AC_build(); 61 f[0][0]=1; 62 for (i=0;i<m;i++) 63 { 64 for (j=0;j<=size;j++) 65 if (f[i][j]&&val[j]==0) 66 { 67 for (k=0;k<26;k++) 68 { 69 f[i+1][ch[j][k]]+=f[i][j]; 70 if (f[i+1][ch[j][k]]>=Mod) f[i+1][ch[j][k]]-=Mod; 71 } 72 } 73 } 74 for (i=0;i<=size;i++) 75 if (val[i]==0) 76 { 77 ans+=f[m][i]; 78 if (ans>=Mod) ans-=Mod; 79 } 80 cout<<(qpow(26,m)-ans+Mod)%Mod; 81 }

[JSOI2007]文本生成器