1. 程式人生 > >hdu 3689 Infinite monkey theorem (KMP+DP)

hdu 3689 Infinite monkey theorem (KMP+DP)

+= code The key archive har 出現 space hdu

題目大意:一群猴子打字,給定猴子輸入每種字符的概率以及輸入次數,求輸出的文本中出現指定字符串的概率

強烈建議看這篇文章:http://www.matrix67.com/blog/archives/366 裏面對這道題的分析很詳細

思路比較清奇,我們先用KMP求出指定串的next,接下來是DP的過程

技術分享圖片表示輸入了i個字符,匹配到了第j個的概率

這道題是一個貪心的思路,我們在第j位可以填上任意字符,而如果第j位填上的字符不符合原串,即在當前第j位匹配失敗,我們要從j-1的位置不斷向前跳next(保證前綴都相同),直到匹配成功或者整個串的無法匹配,然後我們乘上該字符出現的概率即可。

 1 #include <cstdio>
 2
#include <algorithm> 3 #include <cstring> 4 #include <vector> 5 #define N 1010 6 #define M 30 7 #define L 12 8 #define mod 1000000007 9 #define ui unsigned int 10 #define ll long long 11 #define dd double 12 #define idx(x) x-‘a‘+1 13 using namespace std; 14 15 int T,n,m,len; 16 int nxt[L];
17 dd f[N][L],c[M]; 18 char t[L]; 19 void get_kmp() 20 { 21 int i=0,j=-1; 22 nxt[0]=-1; 23 while(i<len) 24 { 25 if(j==-1||t[i]==t[j]) 26 { 27 i++; 28 j++; 29 nxt[i]=j; 30 }else{ 31 j=nxt[j]; 32 } 33 }
34 } 35 36 dd solve() 37 { 38 f[0][0]=1; 39 for(int i=1;i<=m;i++) 40 { 41 for(int j=1;j<=len;j++) 42 { 43 for(int k=1;k<=26;k++) 44 { 45 int p=j-1; 46 while(p!=-1&&idx(t[p])!=k) p=nxt[p]; 47 f[i][p+1] += f[i-1][j-1]*c[k]; 48 } 49 } 50 } 51 dd ans=0; 52 for(int i=1;i<=m;i++) ans+=f[i][len]; 53 return ans*(dd)100; 54 } 55 56 int main() 57 { 58 //freopen("aa.in","r",stdin); 59 while(1) 60 { 61 memset(f,0,sizeof(f)); 62 memset(c,0,sizeof(c)); 63 memset(nxt,0,sizeof(nxt)); 64 scanf("%d%d",&n,&m); 65 if(n==0&&m==0) break; 66 for(int i=1;i<=n;i++) 67 { 68 scanf("%s",t); 69 scanf("%lf",&c[idx(t[0])]); 70 } 71 memset(t,0,sizeof(t)); 72 scanf("%s",t); 73 len=strlen(t); 74 get_kmp(); 75 printf("%.2lf",solve()); 76 putchar(%); 77 puts(""); 78 } 79 return 0; 80 } 81 82 83

hdu 3689 Infinite monkey theorem (KMP+DP)