2017.8.14 文本生成器 失败总结

来源:互联网 发布:管家婆erp是什么软件 编辑:程序博客网 时间:2024/06/06 03:01

        以后凡是在一个中出现>=1次的题就直接转0次用容斥好了、  

        然后剩下的就是怎么找一个单词也不出现的文本的个数了

        显然,这种计数类问题需要用dp  ,而且我们需要知道所有单词会为我们添加字母造成影响,所以需要用ac自动机,跳过所有标记的单词 

           以前是写的指针ac自动机,但它不好写而且巨慢、 所以换了数组

           要注意用0表示null   1表示root   为了方便,我们将0的所有下一个赋为root    同时这个失配指针是指向最近的和自己相同的字母   root可表示所有字母..

           而且失配是单词这个点也不能取,,因为

    


       然后sp数组开小了溢出导致f数组储存信息错误、、查了1.5h才查出来



码:

#include<iostream>#include<cstdio>#include<cstring> #include<queue>using namespace std;queue<int>q;int sz=1,ans1,ans2,n,m,i,j,sp[7000],ch[7000][27],dc[7000],f[105][7000];char str[105];#define P 10007 void ins(){int l=strlen(str),i,o=1;for(i=0;i<l;i++){int zm=str[i]-'A'+1;if(ch[o][zm])o=ch[o][zm];else o=ch[o][zm]=++sz;}dc[o]=1;} void shipei(){int i;sp[1]=0;q.push(1);        while(!q.empty())        {int st=q.front();q.pop();for(i=1;i<=26;i++){        if(ch[st][i]==0)continue;int k=sp[st];while(!ch[k][i])k=sp[k];sp[ch[st][i]]=ch[k][i];if(dc[ch[k][i]])dc[ch[st][i]]=1;    q.push(ch[st][i]);}        }}void dp(int x){int i,j;for(i=1;i<=sz;i++){if(dc[i]||!f[x-1][i])continue;for(j=1;j<=26;j++){int k=i;while(!ch[k][j])k=sp[k];    f[x][ch[k][j]]=(f[x][ch[k][j]]+f[x-1][i])%P;//if(x<2)cout<<f[x][ch[k][j]]<<" ";}}}int main(){ans2=1;scanf("%d%d",&n,&m);for(i=1;i<=26;i++)ch[0][i]=1;f[0][1]=1;for(i=1;i<=n;i++){scanf("%s",str);ins();}shipei();for(i=1;i<=m;i++)dp(i);for(i=1;i<=m;i++)ans2=(ans2*26)%P;for(i=1;i<=sz;i++)if(!dc[i])ans1=(ans1+f[m][i])%P;printf("%d",(ans2-ans1+P)%P);}





   

原创粉丝点击