http://acm.hdu.edu.cn/showproblem.php?pid=2825
10 2 2 hello world 4 1 1 icpc 10 0 0 0 0 0
2 1 14195065
/** hdu2825 AC自动机+状态压缩DP 题目大意:给定一些模式串,求能够造出多少长度为n的字符串,使其包含至少L个模式串 解题思路:建立自动机,每个串代表对应一个二进制位,由于模式串数量很少,我们把他压到一个数里面。 dp[i][j][p]表示长度为i以节点j结尾,并且含有字符串个数的状态为p时的个数 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #include <queue> using namespace std; const int mod=20090717; int n,m,k; int dp[30][110][1<<10]; int num[5000]; struct Trie { int next[110][26],fail[110],end[110]; int root,L; int newnode() { for(int i=0; i<26; i++) { next[L][i]=-1; } end[L++]=0; return L-1; } void init() { L=0; root=newnode(); } void insert(char *buf,int id) { int len=strlen(buf); int now=root; for(int i=0; i<len; i++) { if(next[now][buf[i]-'a']==-1) { next[now][buf[i]-'a']=newnode(); } now=next[now][buf[i]-'a']; } end[now]|=(1<<id); } void build() { queue<int>Q; fail[root]=root; for(int i=0; i<26; i++) { if(next[root][i]==-1) next[root][i]=root; else { fail[next[root][i]]=root; Q.push(next[root][i]); } } while(!Q.empty()) { int now=Q.front(); Q.pop(); end[now]|=end[fail[now]]; for(int i=0; i<26; i++) { if(next[now][i]==-1) next[now][i]=next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } } int solve() { for(int i=0; i<=n; i++) { for(int j=0; j<L; j++) { for(int p=0; p<(1<<m); p++) { dp[i][j][p]=0; } } } dp[0][0][0]=1; for(int i=0; i<n; i++) { for(int j=0; j<L; j++) { for(int p=0; p<(1<<m); p++) { if(dp[i][j][p]>0) { for(int x=0; x<26; x++) { int newi=i+1; int newj=next[j][x]; int newp=(p|end[newj]); dp[newi][newj][newp]+=dp[i][j][p]; dp[newi][newj][newp]%=mod; } } } } } int ans=0; for(int p=0; p<(1<<m); p++) { if(num[p]<k)continue; for(int i=0; i<L; i++) { ans=(ans+dp[n][i][p])%mod; } } return ans; } } ac; char buf[20]; int main() { for(int i=0; i<(1<<10); i++) { num[i]=0; for(int j=0; j<10; j++) { if(i&(1<<j)) num[i]++; } } while(~scanf("%d%d%d",&n,&m,&k)) { if(n==0&&m==0&&k==0)break; ac.init(); for(int i=0; i<m; i++) { scanf("%s",buf); ac.insert(buf,i); } ac.build(); printf("%d\n",ac.solve()); } return 0; }