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. select 文字右对齐

    select { direction: rtl; } select option { direction: ltr; }

  2. 统计iOS产品不同渠道的下载量

    如何统计iOS产品不同渠道的下载量? 一.前言 在开发过程中,Android可能会打出来很多的包,用于标识不同的商店下载量.原来觉得苹果只有一个商店:AppStore,如何做出不同来源的统计呢?本篇文 ...

  3. Angularjs基础(十二)

    ng-model-options 描述:规定如何更新模型 实例: 在失去焦点时绑定输入框的值scope 变量中. <div ng-app="myApp" ng-control ...

  4. .net mvc里AutoMapper更为便捷的使用方法

    前言:AutoMapper的下载安装我就不多说了,网上百度一大堆.今天我就说说它的更为简单的使用,什么叫更为简单呢?按照一般的使用方法,我们首先建DTO,然后建每个对应的Profile,然后还要把每个 ...

  5. Linux下NFS服务器的搭建与配置(转载)

    一.NFS服务简介 NFS 就是 Network FileSystem 的缩写,最早之前是由sun 这家公司所发展出来的. 它最大的功能就是可以透过网络,让不同的机器.不同的操作系统.可以彼此分享个别 ...

  6. css跨浏览器大全

    CSS技巧1.div的垂直居中问题 vertical-align:middle; 将行距增加到和整个DIV一样高 line-height:200px; 然后插入文字,就垂直居中了.缺点是要控制内容不要 ...

  7. weex踩坑记录

    weex框架样式问题--我暂时使用最基本的样式css,weex前端开发的话web端会显示各种的html标签.写出的样式也都会显示的很好,但是在app端的话,就没有很好的兼容性,只是支持文档中的一些标签 ...

  8. ECSHOP和SHOPEX快递单号查询国际EMS插件V8.6专版

    发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...

  9. thinkphp-PHP实现pdf导出功能

    Thinkphp框架引用tcpdf插件,插件下载地址:待续... 代码编写前先引入tcpdf整个文件夹到项目目录的ThinkPHP文件夹下 如:/ThinkPHP/Library/Vendor/tcp ...

  10. ZooKeeper异常:Error connecting service It is probably not running

    ZooKeeper安装后使用以下命令可以启动成功 bin/zkServer.sh start 但是使用下面命令查看启动状态,则报错误: bin/zkServer.sh status Error con ...