• HDU 3689 Infinite monkey theorem(DP+trie+自动机)(2010 Asia Hangzhou Regional Contest)


    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.

    题目大意:有n个字母,每个字母有一个敲击概率,敲m次,问敲m次之后的串包含给出子串的概率是多少。

    思路:对子串建立一个trie树,建一个自动机(像我这种懒得想的人会先建出一个AC自动机),得出每个点走一步到达的位置。然后DP,dp[m][x]为第m步走到第x个点的概率,最后把dp[m][x]加起来,再拿1-sum就是答案了。

    PS:其实我觉得直接KMP也可以……反正给出的串很短……

    代码(0MS):

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <queue>
      5 using namespace std;
      6 
      7 struct Node {
      8     Node *go[26], *fail;
      9     int id;
     10     Node(int i = 0) {
     11         id = i;
     12         memset(go, 0, sizeof(go));
     13         fail = 0;
     14     }
     15 };
     16 
     17 void build(Node *root, char *str) {
     18     Node *p = root;
     19     for(int i = 0; str[i]; ++i) {
     20         int index = str[i] - 'a';
     21         if(!p->go[index]) p->go[index] = new Node(i + 1);
     22         p = p->go[index];
     23     }
     24 }
     25 
     26 void makeFail(Node *root) {
     27     queue<Node*> que; que.push(root);
     28     while(!que.empty()) {
     29         Node *tmp = que.front(); que.pop();
     30         for(int i = 0; i < 26; ++i) {
     31             if(!tmp->go[i]) continue;
     32             if(tmp == root) tmp->go[i]->fail = root;
     33             else {
     34                 Node *p = tmp->fail;
     35                 while(p) {
     36                     if(p->go[i]) {
     37                         tmp->go[i]->fail = p->go[i];
     38                         break;
     39                     }
     40                     p = p->fail;
     41                 }
     42                 if(!p) tmp->go[i]->fail = root;
     43             }
     44             que.push(tmp->go[i]);
     45         }
     46     }
     47     root->fail = root;
     48 }
     49 
     50 void makeGo(Node *root, char *str) {
     51     Node *tmp = root;
     52     for(int i = 0; i < 26; ++i)
     53         if(i != str[0] - 'a') root->go[i] = root;
     54     for(int i = 0; str[i]; ++i) {
     55         int index = str[i] - 'a';
     56         tmp = tmp->go[index];
     57         for(int j = 0; j < 26; ++j) {
     58             Node *p = tmp;
     59             while(true) {
     60                 if(p->go[j]) {
     61                     tmp->go[j] = p->go[j];
     62                     break;
     63                 }
     64                 p = p->fail;
     65                 if(p == root) break;
     66             }
     67             if(p == root) tmp->go[j] = root->go[j];
     68         }
     69     }
     70 }
     71 
     72 int n, m;
     73 char s[13];
     74 double dp[2][13];
     75 double pro[30];
     76 
     77 double solve(Node *root) {
     78     int cur = 0, len = strlen(s);
     79     dp[cur][0] = 1;
     80     for(int i = 1; i <= len; ++i) dp[cur][i] = 0;
     81     for(int t = 0; t < m; ++t) {
     82         for(int i = 0; i <= len; ++i) dp[cur ^ 1][i] = 0;
     83         for(int i = 0; i < 26; ++i)
     84             dp[cur ^ 1][root->go[i]->id] += pro[i] * dp[cur][0];
     85         Node *tmp = root;
     86         for(int i = 0; i < len - 1; ++i) {
     87             int index = s[i] - 'a';
     88             tmp = tmp->go[index];
     89             for(int j = 0; j < 26; ++j)
     90                 dp[cur ^ 1][tmp->go[j]->id] += pro[j] * dp[cur][i + 1];
     91         }
     92         cur ^= 1;
     93         //for(int i = 0; i <= len; ++i) printf("%.6f ", dp[cur][i]); printf("
    ");
     94     }
     95     double ret = 0;
     96     for(int i = 0; i < len; ++i) {
     97         ret += dp[cur][i];
     98     }
     99     return 1 - ret;
    100 }
    101 
    102 int main() {
    103     while(scanf("%d%d", &n, &m) != EOF) {
    104         if(n == 0 && m == 0) break;
    105         char c; double x;
    106         for(int i = 0; i < 26; ++i) pro[i] = 0;
    107         for(int i = 0; i < n; ++i)
    108             scanf(" %c%lf", &c, &x), pro[c - 'a'] = x;
    109         scanf("%s", s);
    110         Node *root = new Node;
    111         build(root, s);
    112         makeFail(root);
    113         makeGo(root, s);
    114         printf("%.2f%%
    ", solve(root) * 100);
    115     }
    116 }
    View Code
  • 相关阅读:
    小白学 Python 爬虫(21):解析库 Beautiful Soup(上)
    小白学 Python 爬虫(20):Xpath 进阶
    小白学 Python 爬虫(19):Xpath 基操
    小白学 Python 爬虫(18):Requests 进阶操作
    Apache + WordPress 从 0 搭建
    小白学 Python 爬虫(17):Requests 基础使用
    小白学 Python 爬虫(16):urllib 实战之爬取妹子图
    小白学 Python 爬虫(15):urllib 基础使用(五)
    小白学 Python 爬虫(14):urllib 基础使用(四)
    小白学 Python 爬虫(13):urllib 基础使用(三)
  • 原文地址:https://www.cnblogs.com/oyking/p/3306477.html
Copyright © 2020-2023  润新知