• 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 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
     
    Recommend
    lcy&zhengfeng   |   We have carefully selected several similar problems for you:  3682 3683 3685 3686 3687 
     
    题意:
      字符集中有cn个字符(最多26个),给出每个字符的出现概率(它们的和保证为1)
      再给出一个子串B
      求:任给一个长度为N的字符串A(只能包含字符集中的cn种字符),使得B是A的子串的概率。
      N<=1000
    分析:

      动态规划+KMP
      想象一边随机生成字符串A,一边用KMP匹配字符串B的过程
      f[i][j]表示随机生成到第i位,此时B串匹配到第j位的概率
      枚举下一位生成字符c,设其生成概率为pc
      假设下一位填c,计算出KMP匹配指针j应该移动到now
      f[i+1][now] += f[i][j]*pc
      已经匹配到第m位的状态不再进行转移
      ans = ∑f[i][m]

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=1005;
    int cn,n,m,fail[N];
    char B[N],key[30];
    double p[30],f[N][N];
    void get_fail(){
        int p=0;fail[1]=0;
        for(int i=2;i<=m;i++){
            while(p>0&&B[i]!=B[p+1]) p=fail[p];
            if(B[i]==B[p+1]) p++;
            fail[i]=p;
        }
    }
    void dp(){
        memset(f,0,sizeof f);
        f[0][0]=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                for(int k=1;k<=cn;k++){
                    int now=j;
                    while(now>0&&key[k]!=B[now+1]) now=fail[now];
                    if(key[k]==B[now+1]) now++;
                    f[i+1][now]+=f[i][j]*p[k];
                }
            }
        }
        double ans=0;
        for(int i=1;i<=n;i++) ans+=f[i][m];
        ans*=100.0;
        printf("%.2lf%%
    ",ans);
    }
    int main(){
        char s[3];
        while(scanf("%d%d",&cn,&n)==2){
            if(!cn&&!n) break;
            for(int i=1;i<=cn;i++){
                scanf("%s %lf",s,&p[i]);
                key[i]=s[0];
            }
            scanf("%s",B+1);
            m=strlen(B+1);
            get_fail();
            dp();
        }
        return 0;
    }
     
  • 相关阅读:
    经济学原理---10 外部性-- 读书笔记
    经济学原理---9应用:国际贸易--- 读书笔记
    人月神话阅读笔记之一
    小水王
    构建之法读书笔记之五
    课堂作业
    时间记录日志
    构建之法读书笔记之四
    查找水王程序
    代码阅读方法与实践阅读笔记01
  • 原文地址:https://www.cnblogs.com/shenben/p/6383166.html
Copyright © 2020-2023  润新知