hdu 2825

AC自动机+DP,AC自动机还是把字符串按后缀分类,每个节点记录串的状态为本节点时会包含哪几个所给出的字符串。ans[i][j][k]表示长度为i状态为j包含的所给出的字符串为k(二进制,每一位1,0表示有没有第i个字符串)的字符串的个数。

  1     #include <iostream>
  2     #include <cstdio>
  3     #include <cstring>
  4     #include <queue>
  5     #define LL long long
  6     using namespace std;
  7     const int mod=20090717;
  8     const int maxn=11;
  9     int ch[maxn*11][26],val[maxn*11],f[maxn*11];
 10     int ans[26][maxn*11][1<<(10)],num[1<<(10)];
 11     int n,m,q,tot,tot2;
 12     void Insert(char *s)
 13     {
 14         int u=0,len=strlen(s),i,tv;
 15         for(i=0;i<len;i++)
 16         {
 17             tv=s[i]-'a';
 18             if(!ch[u][tv]) ch[u][tv]=tot++;
 19             u=ch[u][tv];
 20         }
 21         val[u]=1<<(tot2++);
 22     }
 23     void getFail()
 24      {
 25          queue<int> q;
 26          f[0]=0;
 27          int i,u;
 28          for(i=0;i<26;i++)
 29          {
 30              u=ch[0][i];
 31              if(u)
 32              {
 33                  f[u]=0;
 34                  q.push(u);
 35              }
 36          }
 37          int v,r;
 38          while(!q.empty())
 39          {
 40              r=q.front();q.pop();
 41              for(i=0;i<26;i++)
 42              {
 43                  u=ch[r][i];
 44                  if(!u) {ch[r][i]=ch[f[r]][i]; }
 45                  else
 46                  {
 47                  q.push(u);
 48                  v=f[r];
 49                  while(v&&!ch[v][i]) v=f[v];
 50                  f[u]=ch[v][i];
 51                  val[u]|=val[f[u]];
 52                  }
 53              }
 54          }
 55      }
 56     int main()
 57     {
 58       //  freopen("1.txt","r",stdin);
 59         num[0]=0;
 60         int i;
 61         for(i=1;i<(1<<10);i++) num[i]=num[i>>1] +(i&1);
 62         while(scanf("%d%d%d",&n,&m,&q))
 63         {
 64             if(!n&&!m&&!q) break;
 65             char s[15];
 66             memset(ch,0,sizeof(ch));
 67             memset(val,0,sizeof(val));
 68             tot=1;tot2=0;
 69             for(i=0;i<m;i++)
 70             {
 71                 scanf("%s",s);
 72                 Insert(s);
 73             }
 74             getFail();
 75             int j,k,w,v;
 76             int M=1<<m;
 77             for(i=0;i<=n;++i)
 78                 for(j=0;j<tot;++j)
 79                     for(k=0;k<M;++k)
 80                         ans[i][j][k]=0;
 81             ans[0][0][0]=1;
 82             for(i=0;i<n;++i)
 83             {
 84                 for(j=0;j<tot;++j)
 85                 {
 86                     for(k=0;k<M;++k)
 87                     {
 88                        if(!ans[i][j][k]) continue;
 89                         for(w=0;w<26;w++)
 90                         {
 91                             v=ch[j][w];
 92                             ans[i+1][v][k|val[v]]=(ans[i+1][v][k|val[v]]+ans[i][j][k])%mod;
 93                         }
 94                     }
 95                 }
 96             }
 97             int sum=0;
 98             for(i=0;i<tot;++i)
 99             {
100                 for(j=0;j<(1<<m);++j)
101                 {
102                     if(num[j]>=q)
103                         sum=(sum+ans[n][i][j])%mod;
104                 }
105             }
106             printf("%d\n",sum);
107         }
108         return 0;
109     }
原文地址:https://www.cnblogs.com/lj030/p/3102579.html