【BZOJ1030】文本生成器(容斥原理,AC自动机,计数DP)

题意:给出n个字符串,求长为m至少包含n个里其中一个的串的字符串一共有多少个,字符集为A到Z,答案对10007取模

n<=60,len<=100

思路:将至少一个转化为所有个数减去没有出现的个数

dp[i][j]表示长度为i,当前在AC自动机上j号节点的方案数

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<string>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<map>
  8 #include<set>
  9 #include<queue>
 10 #include<vector>
 11 using namespace std;
 12 typedef long long ll;
 13 typedef unsigned int uint;
 14 typedef unsigned long long ull;
 15 typedef pair<int,int> PII;
 16 typedef vector<int> VI;
 17 #define fi first
 18 #define se second
 19 #define MP make_pair
 20 #define N   110
 21 #define M   7010
 22 #define eps 1e-8
 23 #define pi  acos(-1)
 24 #define oo  1e9
 25 #define MOD 10007
 26 
 27 int dp[N][M],nxt[M][27],c[M],fa[M],q[M*20],cnt,n,m,len;
 28 char b[M];
 29 
 30 void build()
 31 {
 32     int u=1;
 33     for(int i=1;i<=len;i++)
 34     {
 35         int t=b[i]-'A'+1;
 36         if(!nxt[u][t]) nxt[u][t]=++cnt;
 37         u=nxt[u][t];
 38     }
 39     c[u]=1;
 40 }
 41             
 42 void acauto()
 43 {
 44     int t=0; int w=1; q[1]=1;
 45     while(t<w)
 46     {
 47         int u=q[++t];
 48         for(int i=1;i<=26;i++)
 49         {
 50              if(nxt[u][i])
 51               {
 52                  int son=nxt[u][i];        
 53                  int p=fa[u];
 54                  if(u==1) fa[son]=1;
 55                   else fa[son]=nxt[p][i];
 56                  q[++w]=son;
 57              }
 58               else
 59               {
 60                  int p=fa[u];
 61                  if(u==1) nxt[u][i]=1;
 62                   else nxt[u][i]=nxt[p][i];
 63               }
 64         }
 65         if(c[fa[u]]) c[u]=1;
 66     }
 67 }
 68 
 69 void update(int &x)
 70 {
 71     if(x>=MOD) x-=MOD;
 72 }
 73 
 74 int main()
 75 {
 76     //freopen("bzoj1030.in","r",stdin);
 77     //freopen("bzoj1030.out","w",stdout);
 78     
 79     scanf("%d%d",&n,&m);
 80     cnt=1;
 81     memset(c,0,sizeof(c));
 82     for(int i=1;i<=n;i++) {scanf("%s",b+1); len=strlen(b+1); build();}
 83     acauto();
 84     //printf("%d\n",cnt);
 85     dp[0][1]=1;
 86     for(int i=1;i<=m;i++)
 87     {
 88         for(int j=1;j<=cnt;j++)
 89          if(!c[j])
 90          {
 91              for(int k=1;k<=26;k++) 
 92              {
 93                  int t=nxt[j][k];
 94                  dp[i][t]=(dp[i][t]+dp[i-1][j])%MOD;
 95             }
 96          }
 97     }
 98     ll ans=1;
 99     for(int i=1;i<=m;i++) ans=ans*26%MOD;
100     for(int i=1;i<=cnt;i++)
101      if(!c[i])
102      {
103          ans-=dp[m][i];
104         ans=(ans%MOD+MOD)%MOD;
105      }
106     printf("%lld\n",ans);
107     return 0;
108 }
109     
110     

 

posted on 2018-10-26 20:55  myx12345  阅读(171)  评论(0编辑  收藏  举报

导航