POJ 1625
什么鬼,真的是有负数的吗?我在字符加上了128才过了。dp[i][j],经过i步到达j状态的路径数。转移很容易了,建个trie图就可以,由前一步可连通到和更新即可。
另外,要用到大数和AC自动机DP
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <climits> 6 #include <string.h> 7 #include <queue> 8 #include <cmath> 9 #include <map> 10 #include <vector> 11 #define LL __int64 12 using namespace std; 13 14 const __int64 forward=100000000000000000LL; 15 const int root=0; 16 const int Maxn=550; 17 int idx[600]; 18 struct BigNumber{ 19 LL num[16]; 20 void initial(){ 21 for(int i=0;i<15;i++) 22 num[i]=0; 23 } 24 }; 25 BigNumber add_BigNumber(BigNumber a,BigNumber b){ 26 BigNumber c; 27 c.initial(); 28 for(int i=0;i<15;i++){ 29 c.num[i]=c.num[i]+a.num[i]+b.num[i]; 30 c.num[i+1]=c.num[i]/forward; 31 c.num[i]%=forward; 32 } 33 return c; 34 } 35 BigNumber dp[510][55]; 36 struct Node{ 37 bool tag; 38 int next[55]; 39 int fail; 40 void initial(){ 41 tag=false; 42 memset(next,-1,sizeof(next)); 43 fail=-1; 44 } 45 }; 46 int que[Maxn],head,tail,tot; 47 Node trie[Maxn]; 48 int dictsize,step; 49 char str[60]; 50 51 void build_ac(){ 52 head=tail=0; 53 que[tail++]=root; 54 int tmp,p; 55 while(head!=tail){ 56 tmp=que[head++]; 57 p=-1; 58 for(int i=0;i<dictsize;i++){ 59 if(trie[tmp].next[i]!=-1){ 60 if(tmp==root) trie[trie[tmp].next[i]].fail=root; 61 else{ 62 p=trie[tmp].fail; 63 while(p!=-1){ 64 if(trie[p].next[i]!=-1){ 65 trie[trie[tmp].next[i]].fail=trie[p].next[i]; 66 break; 67 } 68 p=trie[p].fail; 69 } 70 if(p==-1) trie[trie[tmp].next[i]].fail=root; 71 } 72 if(trie[trie[trie[tmp].next[i]].fail].tag) 73 trie[trie[tmp].next[i]].tag=true; 74 que[tail++]=trie[tmp].next[i]; 75 } 76 else{ //trie[tmp].next[i]==-1 77 if(tmp==root) trie[tmp].next[i]=root; 78 else{ 79 p=trie[tmp].fail; 80 while(p!=-1){ 81 if(trie[p].next[i]!=-1){ 82 trie[tmp].next[i]=trie[p].next[i]; 83 break; 84 } 85 p=trie[p].fail; 86 } 87 if(p==-1) trie[tmp].next[i]=root; 88 } 89 } 90 } 91 } 92 } 93 94 int main(){ 95 int n,m,p,pt; 96 cin>>n>>m>>p; 97 for(int i=0;i<Maxn;i++) trie[i].initial(); 98 head=tail=tot=0; 99 dictsize=n; step=m; 100 cin>>str; 101 for(int i=0;i<n;i++) 102 idx[str[i]+128]=i; 103 // cout<<idx['a']<<endl; 104 // cout<<idx['b']<<endl; 105 for(int i=0;i<p;i++){ 106 cin>>str; 107 pt=root;int k=0; 108 int len=strlen(str); 109 while(k<len){ 110 if(trie[pt].next[idx[str[k]+128]]==-1) trie[pt].next[idx[str[k]+128]]=++tot; 111 pt=trie[pt].next[idx[str[k]+128]]; 112 k++; 113 } 114 trie[pt].tag=true; 115 } 116 // cout<<"YES"<<endl; 117 build_ac(); 118 // cout<<"YEA"<<endl; 119 for(int i=0;i<=tot;i++){ 120 for(int j=0;j<=step;j++) 121 dp[i][j].initial(); 122 } 123 dp[0][0].num[0]=1; 124 for(int k=0;k<step;k++){ 125 for(int i=0;i<=tot;i++){ 126 if(!trie[i].tag){ 127 for(int j=0;j<dictsize;j++){ 128 if(!trie[trie[i].next[j]].tag) 129 dp[trie[i].next[j]][k+1]=add_BigNumber(dp[trie[i].next[j]][k+1],dp[i][k]); 130 } 131 } 132 } 133 } 134 BigNumber ans; 135 ans.initial(); 136 // cout<<tot<<endl; 137 for(int i=0;i<=tot;i++){ 138 if(!trie[i].tag){ 139 ans=add_BigNumber(ans,dp[i][step]); 140 } 141 } 142 bool flag=false; 143 for(int i=14;i>=1;i--) 144 if(ans.num[i]>0||flag){ 145 if(flag) 146 printf("%017I64d",ans.num[i]); 147 else 148 printf("%I64d",ans.num[i]); 149 flag=true; 150 } 151 if(flag) 152 printf("%017I64d\n",ans.num[0]); 153 else{ 154 printf("%I64d\n",ans.num[0]); 155 } 156 return 0; 157 }