【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
null