[bzoj1030][JSOI2007]文本生成器

  AC自动机入门题。。。。

  然而我只想入门以防KOI出题人送分(其实是智商硬伤)。。。YY一下感觉AC自动机还很正常然而写起来就各种跪

  显然是用总的串数减去不可读的串数。。。而不可读串数就是AC自动机上走m步(从根出发),并且不经过任何一个完整的可识别单词的路径数。

  “不经过任何一个完整的可识别单词”就是说走的每个节点都不是结束节点,并且fail指针指向的也不是结束节点。(这就保证从根到这个节点上的路径不包含完整的单词)

  把AC自动机建出来,然后在上面dp

  f[i][j]表示走了i步,最后在自动机的j号节点上的路径数。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 using namespace std;
 6 const int sxt=10007;const int maxn=66;const int maxlen=103;
 7 
 8 int fail[maxn*maxlen],ch[maxn*maxlen][26],dl[maxn*maxlen],tot,len,l,r;
 9 bool tag[maxn*maxlen];//是结尾节点,或者fail指向结尾节点 
10 char s[maxlen];
11 
12 int f[2][maxn*maxlen],pre,now;
13 int i,j,k,n,m,ans;
14 
15 inline void insert(int len){
16     register int i,now;
17     for(i=1;i<=len;i++)s[i]-='A';
18     for(now=0,i=1;i<=len;i++)
19         now=ch[now][s[i]]?ch[now][s[i]]:ch[now][s[i]]=++tot;
20     tag[now]=1;
21 }
22 inline void getfail(){
23     register int i,j,tmp;
24     l=0,r=1,dl[1]=0;
25     while(l<r)
26         for(j=0,i=dl[++l];j<26;j++)if(ch[i][j]){
27             for(tmp=fail[i];tmp&&!ch[tmp][j];tmp=fail[tmp]);
28             fail[ch[i][j]]=i?ch[tmp][j]:0,
29             tag[ch[i][j]]|=tag[ch[tmp][j]];
30             dl[++r]=ch[i][j];
31         }    
32 }
33 
34 int main(){
35     register int j,k,tmp;
36     scanf("%d%d",&n,&m);
37     for(i=ans=1;i<=m;i++){
38         ans*=26;if(ans>=sxt)ans%=sxt;
39     }
40     for(i=1;i<=n;i++){
41         for(s[len=1]=getchar();s[1]<'A'||s[1]>'Z';s[1]=getchar());
42         while(s[len]>='A'&&s[len]<='Z')s[++len]=getchar();
43         len--,insert(len);
44     }
45     getfail();
46     f[0][0]=1;
47     for(i=1,now=1,pre=0;i<=m;i++,swap(now,pre))
48         for(memset(f[now],0,(tot+1)<<2),j=dl[l=1];l<=r;j=dl[++l])if(!tag[j]&&f[pre][j])
49         for(k=0;k<26;k++){
50             for(tmp=j;tmp&&!ch[tmp][k];tmp=fail[tmp]);
51             tmp=ch[tmp][k];
52             if(!tag[tmp])
53             f[now][tmp]+=f[pre][j],f[now][tmp]-=f[now][tmp]>=sxt?sxt:0;
54         }
55     for(i=0;i<=tot;i++)
56         ans-=f[pre][i],ans+=ans<0?sxt:0;
57     printf("%d
",ans);
58     return 0;
59 }
View Code

代码跑得奇慢而且毫无可读性QAQ

原文地址:https://www.cnblogs.com/czllgzmzl/p/5185964.html