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):

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; struct Node {
Node *go[], *fail;
int id;
Node(int i = ) {
id = i;
memset(go, , sizeof(go));
fail = ;
}
}; void build(Node *root, char *str) {
Node *p = root;
for(int i = ; str[i]; ++i) {
int index = str[i] - 'a';
if(!p->go[index]) p->go[index] = new Node(i + );
p = p->go[index];
}
} void makeFail(Node *root) {
queue<Node*> que; que.push(root);
while(!que.empty()) {
Node *tmp = que.front(); que.pop();
for(int i = ; i < ; ++i) {
if(!tmp->go[i]) continue;
if(tmp == root) tmp->go[i]->fail = root;
else {
Node *p = tmp->fail;
while(p) {
if(p->go[i]) {
tmp->go[i]->fail = p->go[i];
break;
}
p = p->fail;
}
if(!p) tmp->go[i]->fail = root;
}
que.push(tmp->go[i]);
}
}
root->fail = root;
} void makeGo(Node *root, char *str) {
Node *tmp = root;
for(int i = ; i < ; ++i)
if(i != str[] - 'a') root->go[i] = root;
for(int i = ; str[i]; ++i) {
int index = str[i] - 'a';
tmp = tmp->go[index];
for(int j = ; j < ; ++j) {
Node *p = tmp;
while(true) {
if(p->go[j]) {
tmp->go[j] = p->go[j];
break;
}
p = p->fail;
if(p == root) break;
}
if(p == root) tmp->go[j] = root->go[j];
}
}
} int n, m;
char s[];
double dp[][];
double pro[]; double solve(Node *root) {
int cur = , len = strlen(s);
dp[cur][] = ;
for(int i = ; i <= len; ++i) dp[cur][i] = ;
for(int t = ; t < m; ++t) {
for(int i = ; i <= len; ++i) dp[cur ^ ][i] = ;
for(int i = ; i < ; ++i)
dp[cur ^ ][root->go[i]->id] += pro[i] * dp[cur][];
Node *tmp = root;
for(int i = ; i < len - ; ++i) {
int index = s[i] - 'a';
tmp = tmp->go[index];
for(int j = ; j < ; ++j)
dp[cur ^ ][tmp->go[j]->id] += pro[j] * dp[cur][i + ];
}
cur ^= ;
//for(int i = 0; i <= len; ++i) printf("%.6f ", dp[cur][i]); printf("\n");
}
double ret = ;
for(int i = ; i < len; ++i) {
ret += dp[cur][i];
}
return - ret;
} int main() {
while(scanf("%d%d", &n, &m) != EOF) {
if(n == && m == ) break;
char c; double x;
for(int i = ; i < ; ++i) pro[i] = ;
for(int i = ; i < n; ++i)
scanf(" %c%lf", &c, &x), pro[c - 'a'] = x;
scanf("%s", s);
Node *root = new Node;
build(root, s);
makeFail(root);
makeGo(root, s);
printf("%.2f%%\n", solve(root) * );
}
}

HDU 3689 Infinite monkey theorem(DP+trie+自动机)(2010 Asia Hangzhou Regional Contest)的更多相关文章

  1. HDU 3689 Infinite monkey theorem [KMP DP]

    Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...

  2. hdu 3689 Infinite monkey theorem

    Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/ ...

  3. HDU 3689 Infinite monkey theorem ——(自动机+DP)

    这题由于是一个单词,其实直接kmp+dp也无妨.建立自动机当然也是可以的.设dp[i][j]表示匹配到第i个字母的时候,在单词中处于第j个位置的概率,因此最终的答案是dp[0~m][len],m是输入 ...

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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3689 黄老师说得对,题目只有做wa了才会有收获,才会有提高. 题意:一个猴子敲键盘,键盘上有n个键,猴 ...

  5. [AC自己主动机+可能性dp] hdu 3689 Infinite monkey theorem

    意甲冠军: 给n快报,和m频率. 然后进入n字母出现的概率 然后给目标字符串str 然后问m概率倍的目标字符串是敲数量. 思维: AC自己主动机+可能性dp简单的问题. 首先建立trie图,然后就是状 ...

  6. ●HDU 3689 Infinite monkey theorem

    题链: http://acm.hdu.edu.cn/showproblem.php?pid=3689题解: KMP,概率dp (字符串都从1位置开始) 首先对模式串S建立next数组. 定义dp[i] ...

  7. HDU 3696 Farm Game(拓扑+DP)(2010 Asia Fuzhou Regional Contest)

    Description “Farm Game” is one of the most popular games in online community. In the community each ...

  8. HDU 3685 Rotational Painting(多边形质心+凸包)(2010 Asia Hangzhou Regional Contest)

    Problem Description Josh Lyman is a gifted painter. One of his great works is a glass painting. He c ...

  9. HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)

    Problem Description City C is really a nightmare of all drivers for its traffic jams. To solve the t ...

随机推荐

  1. papers-06-02

    午睡被同事吵醒,只好干活.看到微信公众号有一篇文章说老朋友呢,点进去发现原来相关的工作好多,而且好新好细致. 微信的文章可以见这里: 探究最陌生的老朋友Softmax 里面的几篇文章可以看看. Lar ...

  2. react setState修改嵌套对象

    在react使用setState过程中,难免会遇到复杂的数据类型,,这里还要提醒一下setState 是异步操作行为,需要setState之后的结果做为参数,请求数据的话,可以配合 async  aw ...

  3. 卸载MySQL以及重装卡到Start Services的解决办法(亲测有效,刚重装成功)

    卸载MySQL以及重装卡到Start Services的解决办法 重装系统永远是个好办法,但是对于我们程序员来说只要一想到电脑上的环境变量和其他的配置就蔫了.所以这一条就当作是废话吧. 一般来说装My ...

  4. spring入门(三) 使用spring mvc

    1.建立project / module 新建空的project:springMvcStudy 新建module:type maven-webapp,名字mvcStudy 2.为module设置Sou ...

  5. Navicat for Mysql中错误提示索引过长1071-max key length is 767 byte

    1.建用户信息表 tb_person_info create table tb_person_info( user_id int(10) auto_increment, `name` varchar( ...

  6. P3818 小A和uim之大逃离 II(bfs,有条件的广搜)

    题目背景 话说上回……还是参见 https://www.luogu.org/problem/show?pid=1373 吧 小a和uim再次来到雨林中探险.突然一阵南风吹来,一片乌云从南部天边急涌过来 ...

  7. docker搭建基于percona-xtradb-cluster方案的mysql集群

    一.部署环境 序号 hostname ip 备注 1 manager107 10.0.3.107 centos7;3.10.0-957.1.3.el7.x86_64 2 worker68 10.0.3 ...

  8. Linux常用文档操作命令--1

    1.查看目录下的文档 a) ls(list):查看目录下的所有文档或者文档的信息. 命令行:ls [-a][-A] [-f][-F][-h][-l][-r][-R][-S][-t] 目录名称  //注 ...

  9. js判断是否为数字

    function isNumber(value) { var patrn = /^(-)?\d+(\.\d+)?$/; if (patrn.exec(value) == null || value = ...

  10. for循环小练习

    for循环是前测试循环语句 for(初始值:判定条件:步长){ 循环语句 } For循环原理: For循环第一次执行:首先执行语句1,然后执行语句2,如果条件为真,向内执行执行循环语句3. 如果条件为 ...