题目链接: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)的更多相关文章

  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 ——(自动机+DP)

    这题由于是一个单词,其实直接kmp+dp也无妨.建立自动机当然也是可以的.设dp[i][j]表示匹配到第i个字母的时候,在单词中处于第j个位置的概率,因此最终的答案是dp[0~m][len],m是输入 ...

  3. 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 ...

  4. hdu 3689 Infinite monkey theorem

    Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/ ...

  5. ●HDU 3689 Infinite monkey theorem

    题链: http://acm.hdu.edu.cn/showproblem.php?pid=3689题解: KMP,概率dp (字符串都从1位置开始) 首先对模式串S建立next数组. 定义dp[i] ...

  6. [AC自己主动机+可能性dp] hdu 3689 Infinite monkey theorem

    意甲冠军: 给n快报,和m频率. 然后进入n字母出现的概率 然后给目标字符串str 然后问m概率倍的目标字符串是敲数量. 思维: AC自己主动机+可能性dp简单的问题. 首先建立trie图,然后就是状 ...

  7. 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 ...

  8. HUD3689 Infinite monkey theorem

    Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/ ...

  9. HDU 4405:Aeroplane chess(概率DP入门)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=4405 Aeroplane chess Problem Description   Hzz loves ...

随机推荐

  1. python 批量请求url

    import urllib2 from urllib import quote f = open("data.in", "r") out = file(&quo ...

  2. R(三): R包原理及安装

    包(package)是多个函数的集合,常作为分享代码的基本单元,代码封装成包可以方便其他用户使用.越来越多的R包正在由世界上不同的人所创建并分发,这些分发的R包,可以从CRAN 或 github 上获 ...

  3. BouncyCastle产生一个PKCS#12规范的PFX/p12证书

    RT,在C#中实现,依赖.netFramework2.0 BouncyCastle中提供了PKCS12Store,Pkcs12StoreBuilder,AsymmetricKeyEntry,X509C ...

  4. 剑指offer系列22--二叉树中和为某一值的路径

    22[题目]输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径. * 路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径 * [思路]只要从根结点到叶结点一条一条遍 ...

  5. RegisterClientScriptBlock 与 RegisterStartupScript 的区别

    RegisterClientScriptBlock.RegisterStartupScript 都是注册一个脚本块. ClientScript.RegisterClientScriptBlock(th ...

  6. Perl 模块 Getopt::Std 和 Getopt::Long

    示例程序: getopt.pl; 1 2 3 4 5 6 7 8 #!/usr/bin/perl -w #use strict; use Getopt::Std; use vars qw($opt_a ...

  7. 从SVN导出指定版本号之间修改的文件

    当一个网站项目进入运营维护阶段以后,不会再频繁地更新全部源文件到服务器,这个时间的修改大多是局部的,因此更新文件只需更新修改过的文件,其他 没有修改过的文件就没有必要上载到服务器.但一个稍微上规模的网 ...

  8. IntentService简介

    参照文章:http://android.tgbus.com/Android/tutorial/201106/355229.shtml IntentService是Service类的子类,用来处理异步请 ...

  9. Hadoop MapReduce编程学习

    一直在搞spark,也没时间弄hadoop,不过Hadoop基本的编程我觉得我还是要会吧,看到一篇不错的文章,不过应该应用于hadoop2.0以前,因为代码中有  conf.set("map ...

  10. php解压 tar.gz 格式文件

    1.运用php自带压缩与归档扩展(phar) $phar = new PharData('song.tar.gz'); //路径 要解压的文件 是否覆盖 $phar->extractTo('c: ...