您的位置:首页 > 其它

HDU 3689 Infinite monkey theorem(字符串匹配+概率dp)

2017-03-30 17:14 453 查看


Infinite monkey theorem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1730    Accepted Submission(s): 901


Problem Description

Could you imaging a monkey writing computer programs? Surely monkeys are smart among animals. But their limited intelligence is no match for our human beings. However, there is a theorem about monkeys, and it states that monkeys can write everything if given
enough time.

The theorem is called “Infinite monkey theorem”. It states that a monkey hitting keys at random on a typewriter keyboard for an infinite amount of time will almost surely type any given text, which of course includes the programs you are about to write (All
computer programs can be represented as text, right?).

It’s very easy to prove this theorem. A little calculation will show you that if the monkey types for an infinite length of time the probability that the output contains a given text will approach 100%.

However, the time used is too long to be physically reasonable. The monkey will not be able to produce any useful programs even if it types until the death of the universe. To verify this and ensure that our human beings are not replaceable by monkeys, you
are to calculate the probability that a monkey will get things right.

 

Input

There will be several test cases.

Each test case begins with a line containing two integers n and m separated by a whitespace (2<=n<=26, 1<=m<=1000). n is the number of keys on the typewriter and the monkey will hit these keys m times. Thus the typewriter will finally produce an output of m
characters.

The following n lines describe keys on the typewriter. Each line has a lower case letter and a real number separated by a whitespace. The letter indicates what the typewriter will produce if the monkey hits that key and the real number indicates the probability
that the monkey will hit this key. Two hits of the monkey are independent of each other (Two different hits have the same probability for a same key), and sum of all the probabilities for each key is ensured to be 1.

The last line of the test case contains a word composed of lower case letters. The length of the word will be less than or equal to 10.

The input will end with a line of two zeros separated by a whitespace. This line should not be processed.

 

Output

For each test case, output one line containing the probability that the given word will appear in the typewriter’s output. The output should be in percentage format and numbers should be rounded to two digits after the decimal point.

 

Sample Input

4 10
w 0.25
o 0.25
r 0.25
d 0.25
word
2 10
a 1.0
b 0.0
abc
2 100
a 0.312345
b 0.687655
abab
0 0

 

Sample Output

2.73%
0.00%
98.54%

 

Source

2010 Asia Hangzhou Regional Contest 

 

Recommend

lcy&zhengfeng   |   We have carefully selected several similar problems for you:  3682 3683 3685 3686 3680 

题目大意:

    有一个猴子,随机地输出一些字符,问输出m次后出现给定字符串的概率。

解题思路:

    题目要求出现的概率,但是我们可以发现直接求出现的概率非常麻烦,于是我们就可以求未出现的概率,然后用1减一下即是答案。

    对于字符串匹配有关的dp,往往可以用匹配长度表示匹配状态。这题也适用。于是我们就可以用dp[i][j]表示添加到第i个字符,匹配到第j位还未匹配成功的概率。状态就很简单了(详细见代码)。不过,有一点需要注意,当无法继续匹配到下一位时,我们就需要重新确定匹配的状态,最优解应该是用kmp或AC自动加进行匹配,不过由于这题匹配字符串最长只有10,所以可以先暴力预处理出转移情况。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <queue>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))

const int MAXN=26+3;
const int MAXM=1000+3;
const int MAXL=10+3;
int N,M,L;
int change[MAXL][MAXN];//存储匹配情况
double rate[MAXN],dp[MAXM][MAXL];
char s[MAXL];//要求的字符串

void init()//初始化
{
mem(dp,0);
for(int i=0;i<26;++i)
rate[i]=0;
}

int main()
{
while(~scanf("%d%d",&N,&M)&&(N||M))
{
init();
for(int i=0;i<N;++i)//输入每个符号出现的概率
{
char s[5];
double r;
scanf("%s%lf",s,&r);
rate[s[0]-'a']=r;
}
s[0]='a';
scanf("%s",s+1);
L=(int)strlen(s)-1;
for(int i=0;i<L;++i)//暴力预处理匹配情况
for(int j=0;j<26;++j)
{
if(s[i+1]==j+'a')
{
change[i][j]=i+1;
continue;
}
int k;
for(k=i;k>0;--k)
{
if(s[k]!=j+'a')
continue;
bool ok=true;
for(int t=0;k-t-1>0;++t)
if(s[k-t-1]!=s[i-t])
{
ok=false;
break;
}
if(ok)
break;
}
change[i][j]=k;
}
dp[0][0]=1;
for(int i=0;i<M;++i)
for(int l=0;l<L;++l)
for(int j=0;j<26;++j)
dp[i+1][change[l][j]]+=dp[i][l]*rate[j];//转移
double ans=0;
for(int i=0;i<L;++i)
ans+=dp[M][i];
printf("%.2f",(1-ans)*100);
putchar('%');
putchar('\n');
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: