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. Spring知识点总结(五)Spring整合JDBC

     1. 回顾JDBC        a. java操作关系型数据的API.导入相关数据库的驱动包后可以通过JDBC提供的接口来操作数据库.        b. 实现JDBC的六个步骤          ...

  2. Python基础—09-文件操作

    文件操作 目录管理(os) system:执行系统命令 # 清空屏幕 # os.system('cls') # 弹出计算器程序 os.system('calc') name:查看系统名称 nt:win ...

  3. 我的第一个Python程序

    #我的第一个Python程序 def is_valid_date(strdate): #判断是否是一个有效的日期字符串 try: #判断是否是时间格式 if ":" in strd ...

  4. jqPaginator分页插件

    如下图效果: 官方地址:http://jqpaginator.keenwon.com/ java后台代码Page对象: /** * * All Rights Reserved. 保留所有权利. */ ...

  5. OCCI开发环境搭建(Ubuntu)

    OCCI开放包(下载与服务器版本相同的开发包, 这用的是12.1.0.2): instantclient-basic-linux.x64-12.1.0.2.0.zip instantclient-sd ...

  6. Git基本使用及工具

    好久没用git管理代码了,最近忙着要实习,一直在看面试题,后天入职了,就提前再复习一下git吧. git比较方便的两个网站,如果你想逼格高就用GitHub(https://github.com/),如 ...

  7. httpd的prefork、worker、event

    Apache(httpd) 有3种核心MPM(Multi-Processing Module,多进程处理模块)工作模式,分别是prefork,worker和event,其中httpd-2.2的even ...

  8. 简单Maven Dos命令语句

    简单Maven Dos命令语句: 打包:mvn package 编译:mvn compile 编译测试程序:mvn test-compile 清空:mvn clean 运行测试:mvn test 生成 ...

  9. 使用百度定位Api获取当前用户登录地址

    最近在做一个商城项目,客户想把网站做成类似于美团的效果,切换地区时,内容也跟随变化.这就要首先解决根据用户id获得地址的问题,最终决定使用百度定位(不适用于搭建反向代理的项目) String url ...

  10. XPath Helper的安装使用

    XPath Helper的安装使用 xpath helper 是一款chrome浏览器插件,主要用来分析当前网页信息的xpath,在抓取数据时一般会使用到xpath. 安装 下载地址:http://c ...