bzoj 1030 fail树dp
dp[i][j][0]代表当前匹配到i号点走了j步且没到过单词节点,1代表到过,直接转移。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 #define mod 10007 7 #define N 6005 8 using namespace std; 9 int ch[N][26];int cnt;int f[N]; 10 int n,m; 11 char s[105]; 12 bool ok[N]; 13 void in() 14 { 15 int l=strlen(s);int now=0; 16 for(int i=0;i<l;i++) 17 { 18 int y=s[i]-'A'; 19 if(!ch[now][y])ch[now][y]=++cnt; 20 now=ch[now][y]; 21 } 22 ok[now]=1; 23 } 24 queue<int>q; 25 void fail() 26 { 27 for(int i=0;i<26;i++) 28 { 29 if(ch[0][i]) 30 { 31 q.push(ch[0][i]); 32 } 33 } 34 while(!q.empty()) 35 { 36 int tmp=q.front();q.pop(); 37 for(int i=0;i<26;i++) 38 { 39 int u=ch[tmp][i]; 40 if(!u) 41 { 42 ch[tmp][i]=ch[f[tmp]][i];continue; 43 } 44 q.push(u);f[u]=ch[f[tmp]][i]; 45 if(ok[f[u]])ok[u]=1; 46 } 47 } 48 } 49 int dp[6005][105][2]; 50 void dpp() 51 { 52 dp[0][0][0]=1; 53 for(int i=0;i<m;i++) 54 { 55 for(int j=0;j<=cnt;j++) 56 { 57 for(int k=0;k<26;k++) 58 { 59 if(ok[ch[j][k]]) 60 { 61 dp[ch[j][k]][i+1][1]+=(dp[j][i][1]+dp[j][i][0]); 62 dp[ch[j][k]][i+1][1]%=mod; 63 } 64 else 65 { 66 dp[ch[j][k]][i+1][1]+=dp[j][i][1];dp[ch[j][k]][i+1][1]%=mod; 67 dp[ch[j][k]][i+1][0]+=dp[j][i][0];dp[ch[j][k]][i+1][0]%=mod; 68 } 69 } 70 } 71 } 72 return ; 73 } 74 int main() 75 { 76 scanf("%d%d",&n,&m); 77 for(int i=1;i<=n;i++) 78 { 79 scanf("%s",s);in(); 80 } 81 fail(); 82 dpp(); 83 int ans=0; 84 for(int i=0;i<=cnt;i++) 85 { 86 ans=(ans+dp[i][m][1])%mod; 87 } 88 cout<<ans<<endl; 89 return 0; 90 }