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. Python 学习笔记(七)Python字符串(二)

    索引和切片 索引  是从0开始计数:当索引值为负数时,表示从最后一个元素(从右到左)开始计数 切片 用于截取某个范围内的元素,通过:来指定起始区间(左闭右开区间,包含左侧索引值对应的元素,但不包含右测 ...

  2. Linux上往mysql中导入SQL文件

    1.首先连上你的服务器 2.进入你安装好的数据库 mysql -uroot -p****, 3.执行命令 source /xxx/xxx.sql   后面是文件的路径 4.如果你要是在本地有数据库管理 ...

  3. 不使用C++ 11的整数转字符串

    蓝桥杯不支持C++11,那么to_string方法就用不了了.C语言提供了一种方法. 首先需要头文件 #include <sstream> 然后进行下面的操作就可以,缺点就是比较耗时. # ...

  4. git 本地分支与远程仓库分支关联

    当我们从远程仓库项目克隆到本地后,会自动创建本地master分支,并且与远程仓库主分支关联.如果我们需要在本地创建一个分支并且与远程仓库的origin/xxx分支关联,则可以通过以下命令实现 git ...

  5. 启用image-filter扩展模块

    进入lnmp目录打开lnmp.conf配置文件 修改Nginx_Modules_Options=' --prefix=/usr/local/nginx --with-http_image_filter ...

  6. windows下上传shell脚本不能运行—将dos模式修改为unix 文件格式

    windows下上传shell脚本至linux,其格式将为dos.dos模式的shell脚本将不能再linux下正确运行,需要修改文件模式为unix. 1 查看文件模式方法 linux服务器上,用vi ...

  7. Vue使用json-server来进行后端数据模拟

    正开发过程中 前后端分离或者不分离 ,接口多半是之后与页面的开发 ,所以建立rest的APL的接口 给前端提供虚拟的数据是非常必要的 所以这里我使用了json-server作为工具,支持CORS和JS ...

  8. C# Regex正则验证规则

    using System; using System.Text.RegularExpressions; namespace MetarCommonSupport { /// <summary&g ...

  9. ARM串口控制终端命令

    配置开发板eth0网络: # ifconfig eth0 10.70.12.168

  10. 转:python教程专题资源免费下载整理合集收藏

    python教程专题资源免费下载整理合集收藏 < Python学习手册(第4版)>(Learning Python, 4th Edition)[PDF] 94MB 简体中文 <Pyt ...