BZOJ 1030 文本生成器 | 在AC自动机上跑DP
题目:
http://www.lydsy.com/JudgeOnline/problem.php?id=1030
题解:
鸽
#include<cstdio> #include<algorithm> #include<cstring> #define p 10007 #define N 6010 using namespace std; int n,m,sze=1,ans1,ans2=1,a[N][27],fail[N],q[N],f[110][N]; char s[110]; bool is[N]; void insert() { int now=1,ch,l=strlen(s); for(int i=0;i<l;i++) { ch=s[i]-'A'+1; if(a[now][ch]) now=a[now][ch]; else now=a[now][ch]=++sze; } is[now]=1; return ; } void acmatch() { int l=0,r=1,now; q[0]=1;fail[1]=0; while(l<r) { now=q[l++]; for(int i=1;i<=26;i++) { if(!a[now][i]) continue; int k=fail[now]; while(!a[k][i]) k=fail[k]; fail[a[now][i]]=a[k][i]; if (is[a[k][i]]) is[a[now][i]]=1; q[r++]=a[now][i]; } } } void dp(int x) { for (int i=1;i<=sze;i++) { if (is[i] || !f[x-1][i]) continue; for (int j=1;j<=26;j++) { int k=i; while (!a[k][j]) k=fail[k]; f[x][a[k][j]]=(f[x][a[k][j]]+f[x-1][i])%p; } } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=26;i++) a[0][i]=1; for (int i=1;i<=n;i++) { scanf("%s",s); insert(); } acmatch(); f[0][1]=1; for (int i=1;i<=m;i++) dp(i); for (int i=1;i<=m;i++) ans2=ans2*26%p; for(int i=1;i<=sze;i++) if(!is[i]) ans1=(ans1+f[m][i])%p; printf("%d",(ans2-ans1+p)%p); return 0; }