[HDU 3689]Infinite monkey theorem (KMP+概率DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3689

黄老师说得对,题目只有做wa了才会有收获,才会有提高。

题意:一个猴子敲键盘,键盘上有n个键,猴子敲第i个键的概率是p[i],问敲m次后形成的字符串里出现给定串的概率是多少。

这实际上就跟那个ac自动机转为trie图然后dp一样的。

类似的题目有POJ 2778,这篇题解不错:http://blog.csdn.net/luyuncheng/article/details/8643001

只不过是一个串,而不是一堆串,因此就可以把AC自动机换为KMP来搞。

设dp[i][j]表示猴子敲了i次键盘走到状态为j的点上

注意next数组的含义,我开始就是没有理解透彻next数组的意思。

如果说str[i]!=c那么str[next[i]]也一定不是c

代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <map>
 6 #include <iterator>
 7 #include <vector>
 8 using namespace std;
 9 typedef long long LL;
10
11 int next[20],n,m;
12 char str[20];
13 double f[30],dp[1100][20];
14
15 void get_next(int m,const char* str){
16     int j = 0;
17     next[1] = 0;
18     for( int i=2;i<m;i++ ){
19         while( j>0 && str[j+1]!=str[i] ) j = next[j];
20         if( str[j+1] == str[i] ) j++;
21         next[i] = j;
22     }
23 }
24
25 int main(){
26     while(scanf("%d%d",&n,&m)!=EOF){
27         if( n==0&&m==0 ) break;
28         char c[2]; double d;
29         memset(f,0,sizeof(f));
30         vector<int> v;
31         for(int i=0;i<n;i++){
32             scanf("%s%lf",c,&d);
33             f[c[0]-‘a‘] = d;
34             v.push_back(c[0]-‘a‘);
35         }
36         scanf("%s",str+1);
37         int len = strlen(str+1);
38         memset(next,0,sizeof(next));
39         get_next(len,str);
40         memset(dp,0,sizeof(dp));
41         dp[0][0] = 100;
42         for(int i=0;i<m;i++){
43             for(int j=0;j<len;j++){
44                 for(int k=0;k<v.size();k++){
45                     int fa = j;
46                     while( fa&&v[k]!=str[fa+1]-‘a‘ ) fa = next[fa];
47                     if( str[fa+1]-‘a‘==v[k] ) fa++;
48                     dp[i+1][fa] += dp[i][j] * f[v[k]];
49                 }
50             }
51         }
52         double sum = 0;
53         for(int i=0;i<=m;i++) sum += dp[i][len];
54         printf("%.2f%%\n",sum);
55     }
56     return 0;
57 }

或者说可以用矩阵来实现

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <map>
 6 #include <iterator>
 7 #include <vector>
 8 using namespace std;
 9 typedef long long LL;
10
11 int next[20],n,m;
12 char str[20];
13 double f[30];
14
15 void get_next(int m,const char* str){
16     int j = 0;
17     next[1] = 0;
18     for( int i=2;i<=m;i++ ){
19         while( j>0 && str[j+1]!=str[i] ) j = next[j];
20         if( str[j+1] == str[i] ) j++;
21         next[i] = j;
22     }
23 }
24
25 struct Matrix{
26     double m[20][20];
27     Matrix(){
28         memset(m,0,sizeof(m));
29     }
30     Matrix operator*(const Matrix &a){
31         Matrix res;
32         for(int i=0;i<20;i++){
33             for(int j=0;j<20;j++){
34                 for(int k=0;k<20;k++){
35                     res.m[i][j] += m[i][k] * a.m[k][j];
36                 }
37             }
38         }
39         return res;
40     }
41 };
42
43 Matrix pow_bin(Matrix x,int e){
44     Matrix res;
45     for(int i=0;i<20;i++) res.m[i][i] = 1;
46     while( e ){
47         if( e&1 ) res = res * x;
48         x = x*x;
49         e>>=1;
50     }
51     return res;
52 }
53
54 int main(){
55     while(scanf("%d%d",&n,&m)!=EOF){
56         if( n==0&&m==0 ) break;
57         char c[2]; double d;
58         vector<int> v;
59         memset(f,0,sizeof(f));
60         for(int i=0;i<n;i++){
61             scanf("%s%lf",c,&d);
62             f[c[0]-‘a‘] = d;
63             v.push_back(c[0]-‘a‘);
64         }
65         getchar();
66         gets(str+1);
67         int len = strlen(str+1);
68         get_next(len,str);
69         Matrix ma;
70         for(int i=0;i<len;i++){
71             for(int j=0;j<v.size();j++){
72                 int fa = i;
73                 while( fa&&str[fa+1]-‘a‘!=v[j] ) fa = next[fa];
74                 if( str[fa+1]-‘a‘==v[j] ) fa++;
75                 ma.m[i][fa] += f[v[j]];
76             }
77         }
78         Matrix res = pow_bin(ma,m);
79         double ans = 0;
80         for(int i=0;i<len;i++){
81             ans += res.m[0][i];
82         }
83         printf("%.2f%%\n",100-ans*100);
84     }
85     return 0;
86 }

矩阵版本

时间: 2024-11-05 23:38:14

[HDU 3689]Infinite monkey theorem (KMP+概率DP)的相关文章

HDU 3689 Infinite monkey theorem [KMP DP]

Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1702 Accepted Submission(s): 882 Problem Description Could you imaging a monkey writing computer programs? Surely monkeys are

[AC自动机+概率dp] hdu 3689 Infinite monkey theorem

题意: 给n个字母,和m次数. 然后输入n个字母出现的概率 然后再给一个目标串str 然后问m次中敲出目标串的概率是多少. 思路: AC自动机+概率dp的简单题. 首先建立trie图,然后就是状态转移了 dp版本: dp三重循环变量次数,节点数,和字母数 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"

●HDU 3689 Infinite monkey theorem

题链: http://acm.hdu.edu.cn/showproblem.php?pid=3689题解: KMP,概率dp (字符串都从1位置开始) 首先对模式串S建立next数组. 定义dp[i][j]表示猴子打的串长度为i,且该串的后缀与模式串最多匹配到j位置的概率. 显然dp[0][0]=1, 考虑如何转移: 枚举下一个打出的字符为c,然后用kmp的next数组找到模式串中可以继续匹配的位置k. 即:k=j+1; while(k&&S[k]!=c) k=next[k]; 然后将dp

HDU 3689 Infinite monkey theorem(KMP + DP)

题目链接:点击打开链接 思路: 用d[i][j]表示前i个字符,已经匹配了字母中的j个字符,最终包含这个字母的概率. 每次转移的时候有n个方向, 表示第i个字符选哪个字符, 那么有个问题, 如果我当前选的这个字符失配了, 那么转移之后我还匹配了多少个字符. 这恰恰是KMP能做的. 细节参见代码: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #inc

hdu 3689 Infinite monkey theorem

TMD这些神奇的猴子... DP里面用KMP的next的数组来搞一搞,(不是很会,一开始想这样搞,然而思路很乱,就弃疗了,,,DP太虚了) 1 #include<bits/stdc++.h> 2 #define N 1000005 3 #define LL long long 4 #define inf 0x3f3f3f3f 5 using namespace std; 6 inline int ra() 7 { 8 int x=0,f=1; char ch=getchar(); 9 whil

hdu 3689 杭州 10 现场 J - Infinite monkey theorem 概率dp kmp

J - Infinite monkey theorem Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 3689 Appoint description:  System Crawler  (2014-11-09) Description Could you imaging a monkey writing computer progra

HUD3689 Infinite monkey theorem

Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1703    Accepted Submission(s): 883 Problem Description Could you imaging a monkey writing computer programs? Surely monke

hdu 4865 Peter&#39;s Hobby(概率dp)

http://acm.hdu.edu.cn/showproblem.php?pid=4865 大致题意:有三种天气和四种叶子状态.给出两个表,分别是每种天气下叶子呈现状态的概率和今天天气对明天天气的概率.给出n天叶子的状态,输出最有可能的天气序列. 思路:wl[i][j]表示天气为i,叶子为j的概率,ww[i][j]表示今天天气为i明天天气为j的概率,st[i]表示第一天天气为i的概率. 对于叶子序列{a1,a2......an},存在一个天气序列{b1,b2......bn},那么总的概率g[

HDU 4336 Card Collector(动态规划-概率DP)

Card Collector Problem Description In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, for example, if you collect all the 108 people in the famous novel Water Margin, you will win an amazing award. As a