1030: [JSOI2007]文本生成器

来源:互联网 发布:华资软件怎么样 编辑:程序博客网 时间:2024/04/27 14:53

题目大意


题解:

AC自动机模板,蒟蒻太菜,把AC自动机忘的差不多了。

然后昨天一天恶补KMP,trie

终于搞完了。

由于直接求合法方案有点难搞,所以我们求不合法的,

f[i][j]表示第i个位置,匹配到j的方案数,

代码:

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<queue>using namespace std;#define mod 10007const int N=6110;int n,m,len;char s[100];bool tf[N];struct node{int fail,a[50];}sa[N];int tot=1,root=1;void build()  {      int len=strlen(s+1);      int x=root;      for(int i=1;i<=len;i++)      {          int c=s[i]-'A';          if(sa[x].a[c]) x=sa[x].a[c];          else x=sa[x].a[c]=++tot;      }      tf[x]=true;  }  queue<int> q;  void make_fail()  {      q.push(root);      while(!q.empty())      {          int x=q.front();q.pop();          for(int i=0;i<26;i++)          {              if(!sa[x].a[i]) continue;              if(x==root) sa[sa[x].a[i]].fail=root;              else              {                    int j=sa[x].fail;                  while(j!=root&&!sa[j].a[i]) j=sa[j].fail;                  sa[sa[x].a[i]].fail=sa[j].a[i];                  if(tf[sa[j].a[i]]) tf[sa[x].a[i]]=true;              }              q.push(sa[x].a[i]);          }      }  }  int f[120][N];void DP(int x){for(int i=1;i<=tot;i++){if(tf[i]||!f[x-1][i]) continue;for(int j=0;j<26;j++){int k=i;while(!sa[k].a[j]) k=sa[k].fail;f[x][sa[k].a[j]]=(f[x-1][i]+f[x][sa[k].a[j]])%mod;}}}int main(){scanf("%d%d",&n,&m);memset(tf,0,sizeof(tf));for(int i=0;i<26;i++) sa[root].a[i]=++tot;for(int i=1;i<=n;i++){scanf("%s",s+1);build();}make_fail();memset(f,0,sizeof(f));f[0][1]=1;for(int i=1;i<=m;i++) DP(i);int ans2=1,ans1=0;for(int i=1;i<=m;i++)         ans2=(ans2*26)%mod;      for(int i=1;i<=tot;i++)         if(!tf[i]) ans1=(ans1+f[m][i])%mod; printf("%d",((ans2-ans1)%mod+mod)%mod);}


原创粉丝点击