Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7250 Accepted Submission(s): 2384
php
題意:node
構造長度是n的字符串其中至少包含k個給定的單詞的方案數。字符集a~zios
代碼:app
//m只有10顯然能夠壓縮,dp[i][j][k]表示構造到到字符串的i位置在樹上的第j節點時包含的單詞狀態是k時的方案數 #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; typedef long long ll; const int MOD=20090717; const int MAXN=100000; int node[109][27],val[109],sz,f[109],dp[26][109][1030]; void init() { sz=0; memset(node[0],0,sizeof(node[0])); val[0]=f[0]=0; } void insert(char *s,int nu) { int len=strlen(s),rt=0; for(int i=0;i<len;i++){ int id=s[i]-'a'; if(!node[rt][id]){ node[rt][id]=++sz; memset(node[sz],0,sizeof(node[sz])); val[sz]=0; } rt=node[rt][id]; } val[rt]|=(1<<nu); } void get_fail() { queue<int>q; for(int i=0;i<26;i++){ int u=node[0][i]; if(u) { q.push(u);f[u]=0; } } while(!q.empty()){ int rt=q.front();q.pop(); for(int i=0;i<26;i++){ int u=node[rt][i]; if(!u){ node[rt][i]=node[f[rt]][i]; continue; } q.push(u); f[u]=node[f[rt]][i]; } val[rt]|=val[f[rt]]; } } void get_dp(int max_sta,int n) { memset(dp,0,sizeof(dp)); dp[0][0][0]=1; for(int i=0;i<n;i++){ for(int j=0;j<=sz;j++){ for(int k=0;k<max_sta;k++){ if(dp[i][j][k]==0) continue; for(int h=0;h<26;h++){ dp[i+1][node[j][h]][k|val[node[j][h]]]+=dp[i][j][k]; dp[i+1][node[j][h]][k|val[node[j][h]]]%=MOD; } } } } } int one(int x) { int s=0; while(x){ s+=x&1; x>>=1; } return s; } int main() { //freopen("in.txt","r",stdin); int n,m,k; char ch[20]; while(scanf("%d%d%d",&n,&m,&k)&&(n+m+k)){ init(); for(int i=0;i<m;i++){ scanf("%s",ch); insert(ch,i); } int max_sta=(1<<m); get_fail(); get_dp(max_sta,n); int ans=0; for(int j=0;j<max_sta;j++){ int tmp=one(j); if(tmp<k) continue; for(int i=0;i<=sz;i++){ ans+=dp[n][i][j]; ans%=MOD; } } printf("%d\n",ans); } return 0; }