[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 ...
随机推荐
- Zabbix的安装与部署---问题处理(php65.6.28 mysqli 报错误 处理)
1)php65.6.28 mysqli 报错误 处理 http://www.xiaochengfu.com/index.php/index/detail/aid/92.html 2)linux下p ...
- OpenSSL进行SSL通讯的一些问题
这两个星期真是被OpenSSL给烦透了,几个很简单基本的问题(如果没人告诉你真的很难测出来)把我搞的..哎,有时候真是不知道自己该不该搞技术,发现自己头脑真是蠢得很... 直接上正题. 第一个问题: ...
- (转)Lambda表达式详解
本文转载自:http://www.cnblogs.com/knowledgesea/p/3163725.html 前言 1.天真热,程序员活着不易,星期天,也要顶着火辣辣的太阳,总结这些东西. 2.夸 ...
- 51nod 1056
n<=10000000000 然后欧拉函数的前缀和可以用莫比乌斯函数的前缀和快速求,注意各种取模 #include<cstdio> typedef long long i64; ,P ...
- Java-Lambda
1. 函数式接口 函数式接口可以包含多个默认方法.类方法,但是只能有一个抽象方法. Lambda表达式的目标类型是函数式接口. java.util.function包下,定义了大量的函数式接口 2. ...
- DDD学习笔记二
参考:感谢博主的分享... http://www.cnblogs.com/netfocus/archive/2012/02/12/2347938.html DDD ==> 领域驱动设计(Doma ...
- 报错:Caused by: java.io.FileNotFoundException: d:\youTemprepository\upload_77faffc1_1580a9240ca__8000_00000001.tmp (系统找不到指定的路径。)
org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-dat ...
- Makefile选项CFLAGS,LDFLAGS,LIBS
CFLAGS 表示用于 C 编译器的选项, CXXFLAGS 表示用于 C++ 编译器的选项.这两个变量实际上涵盖了编译和汇编两个步骤. CFLAGS: 指定头文件(.h文件)的路径,如:CFLAGS ...
- Linux LVM简明教程
逻辑卷管理LVM是一个多才多艺的硬盘系统工具.无论在Linux或者其他类似的系统,都是非常的好用.传统分区使用固定大小分区,重新调整大小十分麻烦.但是,LVM可以创建和管理“逻辑”卷,而不是直接使用物 ...
- SpringMVC参数类型转化错误调试方法