[HDU 3689]Infinite monkey theorem (KMP+概率DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3689
黄老师说得对,题目只有做wa了才会有收获,才会有提高。
题意:一个猴子敲键盘,键盘上有n个键,猴子敲第i个键的概率是p[i],问敲m次后形成的字符串里出现给定串的概率是多少。
这实际上就跟那个ac自动机转为trie图然后dp一样的。
类似的题目有POJ 2778,这篇题解不错:http://blog.csdn.net/luyuncheng/article/details/8643001
只不过是一个串,而不是一堆串,因此就可以把AC自动机换为KMP来搞。
设dp[i][j]表示猴子敲了i次键盘走到状态为j的点上
注意next数组的含义,我开始就是没有理解透彻next数组的意思。
如果说str[i]!=c那么str[next[i]]也一定不是c
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <iterator>
#include <vector>
using namespace std;
typedef long long LL; int next[],n,m;
char str[];
double f[],dp[][]; void get_next(int m,const char* str){
int j = ;
next[] = ;
for( int i=;i<m;i++ ){
while( j> && str[j+]!=str[i] ) j = next[j];
if( str[j+] == str[i] ) j++;
next[i] = j;
}
} int main(){
while(scanf("%d%d",&n,&m)!=EOF){
if( n==&&m== ) break;
char c[]; double d;
memset(f,,sizeof(f));
vector<int> v;
for(int i=;i<n;i++){
scanf("%s%lf",c,&d);
f[c[]-'a'] = d;
v.push_back(c[]-'a');
}
scanf("%s",str+);
int len = strlen(str+);
memset(next,,sizeof(next));
get_next(len,str);
memset(dp,,sizeof(dp));
dp[][] = ;
for(int i=;i<m;i++){
for(int j=;j<len;j++){
for(int k=;k<v.size();k++){
int fa = j;
while( fa&&v[k]!=str[fa+]-'a' ) fa = next[fa];
if( str[fa+]-'a'==v[k] ) fa++;
dp[i+][fa] += dp[i][j] * f[v[k]];
}
}
}
double sum = ;
for(int i=;i<=m;i++) sum += dp[i][len];
printf("%.2f%%\n",sum);
}
return ;
}
或者说可以用矩阵来实现
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <iterator>
#include <vector>
using namespace std;
typedef long long LL; int next[],n,m;
char str[];
double f[]; void get_next(int m,const char* str){
int j = ;
next[] = ;
for( int i=;i<=m;i++ ){
while( j> && str[j+]!=str[i] ) j = next[j];
if( str[j+] == str[i] ) j++;
next[i] = j;
}
} struct Matrix{
double m[][];
Matrix(){
memset(m,,sizeof(m));
}
Matrix operator*(const Matrix &a){
Matrix res;
for(int i=;i<;i++){
for(int j=;j<;j++){
for(int k=;k<;k++){
res[i][j] += m[i][k] * a[k][j];
}
}
}
return res;
}
Matrix operator*= (const Matrix &a){
return *this = operator*(a);
}
const double* operator[] (size_t idx) const{
return m[idx];
}
double* operator[] (size_t idx) {
return m[idx];
}
}; Matrix pow_bin(Matrix x,int e){
Matrix res;
for(int i=;i<;i++) res.m[i][i] = ;
while( e ){
if( e& ) res *= x;
x*=x;
e>>=;
}
return res;
} int main(){
while(scanf("%d%d",&n,&m)!=EOF){
if( n==&&m== ) break;
char c[]; double d;
vector<int> v;
memset(f,,sizeof(f));
for(int i=;i<n;i++){
scanf("%s%lf",c,&d);
f[c[]-'a'] = d;
v.push_back(c[]-'a');
}
getchar();
gets(str+);
int len = strlen(str+);
get_next(len,str);
Matrix ma;
for(int i=;i<len;i++){
for(int j=;j<v.size();j++){
int fa = i;
while( fa&&str[fa+]-'a'!=v[j] ) fa = next[fa];
if( str[fa+]-'a'==v[j] ) fa++;
ma[i][fa] += f[v[j]];
}
}
Matrix res = pow_bin(ma,m);
double ans = ;
for(int i=;i<len;i++){
ans += res[][i];
}
printf("%.2f%%\n",-ans*);
}
return ;
}
矩阵版本
[HDU 3689]Infinite monkey theorem (KMP+概率DP)的更多相关文章
- HDU 3689 Infinite monkey theorem [KMP DP]
Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- HDU 3689 Infinite monkey theorem ——(自动机+DP)
这题由于是一个单词,其实直接kmp+dp也无妨.建立自动机当然也是可以的.设dp[i][j]表示匹配到第i个字母的时候,在单词中处于第j个位置的概率,因此最终的答案是dp[0~m][len],m是输入 ...
- 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 ani ...
- hdu 3689 Infinite monkey theorem
Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/ ...
- ●HDU 3689 Infinite monkey theorem
题链: http://acm.hdu.edu.cn/showproblem.php?pid=3689题解: KMP,概率dp (字符串都从1位置开始) 首先对模式串S建立next数组. 定义dp[i] ...
- [AC自己主动机+可能性dp] hdu 3689 Infinite monkey theorem
意甲冠军: 给n快报,和m频率. 然后进入n字母出现的概率 然后给目标字符串str 然后问m概率倍的目标字符串是敲数量. 思维: AC自己主动机+可能性dp简单的问题. 首先建立trie图,然后就是状 ...
- hdu 3689 杭州 10 现场 J - Infinite monkey theorem 概率dp kmp 难度:1
J - Infinite monkey theorem Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d &am ...
- HUD3689 Infinite monkey theorem
Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/ ...
- HDU 4405:Aeroplane chess(概率DP入门)
http://acm.split.hdu.edu.cn/showproblem.php?pid=4405 Aeroplane chess Problem Description Hzz loves ...
随机推荐
- mysql.server 文件修改起动多实例
如果你用mysql.server来启动的话,就要注意一下点,要修改一下里面的内容,修改如下:大约218行左右 查看复制打印? then print_defaults="$bindir/mys ...
- ORA-01109:数据库未打开
ORA-01109:数据库未打开 在此之前做了这样一操作,在plsql创建了2表空间,由于装的是oracle精简版所以创建表空间大小超过4G就不能创建,然后我就手动把表空间给删除了,回收站也给删了,问 ...
- HTML 图像
通过使用 HTML,可以在文档中显示图像. 实例 插入图像 本例演示如何在网页中显示图像. 从不同的位置插入图片 本例演示如何将其他文件夹或服务器的图片显示到网页中. (可以在本页底端找到更多实例.) ...
- Hibernate延迟加载机制详解
摘自 http://blog.chinaunix.net/uid-20577907-id-3129234.html 1 延迟加载: 延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是 ...
- CryptoAPI与openssl RSA非对称加密解密(PKCS1 PADDING)交互
(以下代码中都只做测试用,有些地方没有释放内存...这个自己解决下) 1.RSA非对称的,首先提供一个供测试用的证书和私钥的数据 1)pem格式的证书和私钥(公私钥是对应的)的base64编码 voi ...
- 多线程要点--CLR C#学习笔记
1.windows永远不会调度一个进程,只调度线程. 2.线程和操作系统的关系:CLR(X)--AppDomain--线程池(包含工作者线程和I/O线程) 3.线程的关键组成部分 A.线程执行上下文 ...
- [转] matlab figure最大化
http://blog.163.com/yinhexiwen@126/blog/static/6404826620122942057214/ % figure 窗口最大化,坐标轴也随着窗口变大而相应变 ...
- SSH_框架整合2—查询显示
4. 完成功能. (1)com.atguigu.ssh.actions包下新建EmployeeAction.java package com.atguigu.ssh.actions; import j ...
- thinkphp中redirect重定向后隐藏index.php
首先,.htaccess文件要配置好隐藏index.php.系统默认生成的就行. 然后,也是最关键的一部,要在Application/Home/Conf里的config.php文件中增加如下配置: & ...
- 拿nodejs快速搭建简单Oauth认证和restful API server攻略
拿nodejs快速搭建简单Oauth认证和restful API server攻略:http://blog.csdn.net/zhaoweitco/article/details/21708955 最 ...