bzoj 1030 文本生成器【AC自动机+dp】

来源:互联网 发布:statnba数据 编辑:程序博客网 时间:2024/06/05 05:52

解题思路:

题目要求至少含有一个单词的方案数,可以转化成总方案数(26m)减去不含有单词的方案数。
接下来把单词插到AC自动机上进行dp。
f[i][j]表示走到AC自动机的j号结点当前单词长度为i的方案数。
转移就是枚举下一位的26个字母,看是否可行(如果下一位在j的子节点中出现,若被标记为单词的结尾,就不能转移)。

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>#include<queue>#define ll long longusing namespace std;int getint(){    int i=0,f=1;char c;    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());    if(c=='-')f=-1,c=getchar();    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';    return i*f;}const int L=105,N=60,p=10007;struct node{    int son[26],fail;    bool end;}tr[N*L];int n,m,tot=1,f[L][N*L];char s[L];queue<int>q;void Insert(){    int len=strlen(s+1),po=1;    for(int i=1;i<=len;i++)    {        if(!tr[po].son[s[i]-'A'])tr[po].son[s[i]-'A']=++tot;        po=tr[po].son[s[i]-'A'];    }    tr[po].end=true;}void build_fail(){    q.push(1);    while(!q.empty())    {        int u=q.front();q.pop();        for(int i=0;i<26;i++)        {            int v=tr[u].fail,w=tr[u].son[i];            while(!tr[v].son[i])v=tr[v].fail;            v=tr[v].son[i];            if(w)tr[w].fail=v,q.push(w),tr[w].end=tr[w].end||tr[v].end;            else tr[u].son[i]=v;        }    }}void solve(){    int ans=1;    for(int i=1;i<=m;i++)ans=ans*26%p;    f[0][1]=1;    for(int i=0;i<m;i++)    {        for(int j=1;j<=tot;j++)            if(!tr[j].end&&f[i][j])            {                for(int k=0;k<26;k++)                {                    int v=j;                    while(!tr[v].son[k])v=tr[v].fail;                    v=tr[v].son[k];                    f[i+1][v]=(f[i+1][v]+f[i][j])%p;                }            }    }    for(int i=1;i<=tot;i++)        if(!tr[i].end)ans=((ans-f[m][i])%p+p)%p;    cout<<ans;}int main(){    //freopen("lx.in","r",stdin);    n=getint(),m=getint();    for(int i=0;i<26;i++)tr[0].son[i]=1;    while(n--)    {        scanf("%s",s+1);        Insert();    }    build_fail();    solve();    return 0;}
原创粉丝点击