10 2 2 hello world 4 1 1 icpc 10 0 0 0 0 0
2 1 14195065
dp[i][j][k]表示长度为i的串在状态j下各串出现情况。
代码:
/* *********************************************** Author :xianxingwuguan Created Time :2014-2-3 13:21:05 File Name :1.cpp ************************************************ */ #pragma comment(linker, "/STACK:102400000,102400000") #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #include <limits.h> #include <string> #include <time.h> #include <math.h> #include <queue> #include <stack> #include <set> #include <map> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-8 #define pi acos(-1.0) typedef long long ll; int dp[30][110][1<<10],num[1<<10]; const int mod=20090717; 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 *str,int id){ int len=strlen(str); int now=root; for(int i=0;i<len;i++){ int p=str[i]-‘a‘; if(next[now][p]==-1) next[now][p]=newnode(); now=next[now][p]; } 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(int n,int m,int k){ 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]) for(int q=0;q<26;q++){ int newi=i+1; int newj=next[j][q]; int newp=p|end[newj]; dp[newi][newj][newp]+=dp[i][j][p]; dp[newi][newj][newp]%=mod; } int ans=0; for(int i=0;i<(1<<m);i++){ if(num[i]<k)continue; for(int j=0;j<L;j++){ ans=(ans+dp[n][j][i])%mod; } } return ans; } }ac; char str[1000]; int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int i,j,k,m,n; for(i=0;i<1024;i++) for(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(i=0;i<m;i++){ scanf("%s",str); ac.insert(str,i); } ac.build(); for(i=0;i<=n;i++) for(j=0;j<ac.L;j++) for(int p=0;p<(1<<m);p++) dp[i][j][p]=0; dp[0][0][0]=1; printf("%d\n",ac.solve(n,m,k)); } return 0; }
原文:http://blog.csdn.net/xianxingwuguan1/article/details/18909205