BZOJ1030: [JSOI2007]文本生成器(AC自动机)

来源:互联网 发布:博实股份是人工智能吗 编辑:程序博客网 时间:2024/05/16 09:47

传送门

题意:
给n个串,和字符串s的长度t。求满足包含至少一个串的字符串s的个数。

题解:
转化为求一个串都不满足的个数。可以直接在AC自动机上DP。

但注意比较坑的一点是如果一个串的子串中有不合法的子串的话也是不合法的。

#include<bits/stdc++.h>using namespace std;const int Maxn=6e3+50;struct node{    node *son[26],*fail;    bool is;    int f[2];    node()    {        fail=NULL;        for(int i=0;i<26;i++)son[i]=NULL;        is=false;f[0]=f[1]=0;    }}Pool[Maxn],*pool=Pool+1,*rt=pool;int n,m,Mod=10007;char ch[105];inline void insert(){    node *pos=rt;int len=strlen(ch+1);    for(int i=1;i<=len;i++)    {        int t=ch[i]-'A';        if(!pos->son[t])        {            pos->son[t]=++pool;        }        pos=pos->son[t];    }    pos->is=true;}inline void buildfail(){    static node* que[Maxn];    static int head,tail;    que[head=tail=1]=rt;    while(head<=tail)    {        node *u=que[head++];        for(int j=0;j<26;j++)        {            node *v=u->fail,*w=u->son[j];            while(!v->son[j])v=v->fail;            if(w)            {                w->fail=v->son[j],que[++tail]=w;                if(w->fail->is)w->is=true;            }            else u->son[j]=v->son[j];        }    }}int main(){    rt->fail=Pool;    for(int i=0;i<26;i++)Pool->son[i]=rt;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        scanf("%s",ch+1);        insert();    }    buildfail();    int now=0;    rt->f[0]=1;    for(int i=1;i<=m;i++)    {        for(node *j=rt;j<=pool;j++)j->f[now^1]=0;        for(node *j=rt;j<=pool;j++)        {            if(j->is)continue;            for(int z=0;z<26;z++)            if(!j->son[z]->is)(j->son[z]->f[now^1]+=j->f[now])%=Mod;        }        now^=1;    }    int ans=0;    for(node *j=rt;j<=pool;j++)if(!j->is)(ans+=j->f[now])%=Mod;    int G=1;    for(int i=1;i<=m;i++)(G*=26)%=Mod;    printf("%d\n",(G-ans+Mod)%Mod);}
原创粉丝点击