题目描述
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 }