[jzoj3472]【NOIP2013模拟联考8】匹配(match)

来源:互联网 发布:瓷砖的重量怎么算法 编辑:程序博客网 时间:2024/06/08 14:18

Description

​ 给定k个字符串以及长度为n的母串可选字母的集合,问母串要完整出现给定的k个字符串的方案数,答案模1000000007,字符仅包含小写字母。

Solution

注意到 k 很小 可以状压

很容易想到利用 AC 自动机 来记录当前匹配到各个字符串的位置

枚举下一个出现的字符即可

注意 在更新时,指针走到了一个节点j,不能只加上这一个节点的贡献,而要把其对应的fail都给更新到

或者 你可以提前把这些点一并考虑

Code

#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define fo(i,x,y) for (int i=(x);i<=(y);++i)#define fd(i,x,y) for (int i=(x);i>=(y);--i)#define oo 2139062143using namespace std;typedef long long ll;typedef double db;const int N=110,M=11,K=9,Mo=1e9+7,LEN=33;const int P=K*LEN;int n,k;char st[K][LEN];int d[P];int all;int f[N][P][256+100];bool bcz[26];int chos[26];struct ACAutoMachine{    int chd[P][26];    int fail[P];    int sz,pt,bz[P];    void insert(char *c,int w)    {        int len=strlen(c),tmp=0;        fo(i,0,len-1)        {            int now=c[i]-'a';            if(!chd[tmp][now])            {                chd[tmp][now]=++sz;                memset(chd[sz],0,sizeof chd[sz]);            }            tmp=chd[tmp][now];        }        bz[tmp]|=(1<<(w-1));    }    bool pd[P];    void Getfail()    {        memset(pd,0,sizeof pd);        int hd=0,tl=0;        pd[0]=1;        fo(i,0,25)        if(chd[0][i]) d[++tl]=chd[0][i],pd[d[tl]]=1;        while(hd++<tl)        {            int now=d[hd];            fo(i,0,25)            if(chd[now][i])            {                int v=chd[now][i];                if(pd[v]) continue;                pd[v]=1;                d[++tl]=v;                int rt=fail[now];                while(!chd[rt][i]&&rt) rt=fail[rt];                fail[v]=chd[rt][i];            }                   }           fo(i,0,sz)        {            bz[i]|=bz[fail[i]];            fo(j,0,25)            {                int p=i;                while(p&&!chd[p][j]) p=fail[p];                if(chd[p][j]) next[i][j]=chd[p][j];                else next[i][j]=0;            }        }    }    int dt[2][P][2];    int tot[2];    int next[P][25];    void solve()    {        memset(f,0,sizeof f);        f[0][0][0]=1;        fo(i,0,n-1)        {            fo(j,0,sz)            {                fo(s,0,all)                if(f[i][j][s])                {                    fo(cc,1,chos[0])                    {                        int c=chos[cc];                        int jj=next[j][c],ss=s|bz[jj];                        f[i+1][jj][ss]=(f[i+1][jj][ss]+f[i][j][s])%Mo;                    }                }            }        }        int ans=0;        fo(i,0,sz)        {            ans=(ans+f[n][i][all])%Mo;        }        printf("%d\n",ans);    }    void clear()    {        memset(bz,0,sizeof bz);        memset(next,0,sizeof next);        memset(fail,0,sizeof fail);        memset(chd[0],0,sizeof chd[0]);         pt=sz=0;    }   }ac;int m;int main(){    scanf("%d%d\n",&n,&k);    fo(i,1,k)    {        scanf("%s\n",st[i]);        ac.insert(st[i],i);    }    ac.Getfail();    scanf("%d\n",&m);    fo(i,1,m)    {        char tp=getchar();        while(!(tp<='z'&&tp>='a')) tp=getchar();        bcz[tp-'a']=1;    }    fo(i,0,25)        if(bcz[i])chos[++chos[0]]=i;            all=(1<<k)-1;    ac.solve();    return 0;}
原创粉丝点击