题目大意:一群猴子打字,给定猴子输入每种字符的概率以及输入次数,求输出的文本中出现指定字符串的概率
强烈建议看这篇文章: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