hdu3689(kmp+概率dp)
2016-07-11 21:05
302 查看
链接:点击打开链接
题意:给出n个字母出现的频率和一个字符串s,求长度为m的字符串含有s的概率
代码:#include <set>
#include <map>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
char s[1005];
int len,nex[1005];
double dp[1005][1005];
map<char,double> mp;
map<char,double>::iterator ite;
void getnext(){
int i,j;
i=0,j=-1;
nex[i]=j;
while(i<len){
if(j==-1||s[i+1]==s[j+1])
nex[++i]=++j;
else
j=nex[j];
} //nex数组也从下标1开始
}
int main(){
char c,fir;
int n,m,i,j,tt;
double pp,ans,sec;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
mp.clear();
for(i=1;i<=n;i++){
cin>>c>>pp;
mp[c]=pp;
}
scanf("%s",s+1);
len=strlen(s+1);
getnext();
for(i=0;i<=m;i++) //dp[i][j]表示长度是i,匹配到子串的j的概率
for(j=0;j<=len;j++) //所以只要求出nex数组直接转移即可,但要注意
dp[i][j]=0; //当第i位匹配到子串最后一位,不要继续转移,否则
dp[0][0]=1; //后面的概率可能变成条件概率
for(i=0;i<m;i++){
for(j=0;j<len;j++){ //就一个子串,没必要直接上自动机...
if(dp[i][j]){
for(ite=mp.begin();ite!=mp.end();ite++){
fir=ite->first;
sec=ite->second;
if(fir==s[j+1])
dp[i+1][j+1]+=(dp[i][j]*sec);
else{
tt=j;
while(tt&&s[tt+1]!=fir)
tt=nex[tt];
if(s[tt+1]==fir)
tt++;
dp[i+1][tt]+=(dp[i][j]*sec);
}
}
}
}
}
ans=0;
for(i=1;i<=m;i++)
ans+=dp[i][len];
printf("%.2lf%%\n",ans*100);
}
return 0;
}
题意:给出n个字母出现的频率和一个字符串s,求长度为m的字符串含有s的概率
代码:#include <set>
#include <map>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
char s[1005];
int len,nex[1005];
double dp[1005][1005];
map<char,double> mp;
map<char,double>::iterator ite;
void getnext(){
int i,j;
i=0,j=-1;
nex[i]=j;
while(i<len){
if(j==-1||s[i+1]==s[j+1])
nex[++i]=++j;
else
j=nex[j];
} //nex数组也从下标1开始
}
int main(){
char c,fir;
int n,m,i,j,tt;
double pp,ans,sec;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
mp.clear();
for(i=1;i<=n;i++){
cin>>c>>pp;
mp[c]=pp;
}
scanf("%s",s+1);
len=strlen(s+1);
getnext();
for(i=0;i<=m;i++) //dp[i][j]表示长度是i,匹配到子串的j的概率
for(j=0;j<=len;j++) //所以只要求出nex数组直接转移即可,但要注意
dp[i][j]=0; //当第i位匹配到子串最后一位,不要继续转移,否则
dp[0][0]=1; //后面的概率可能变成条件概率
for(i=0;i<m;i++){
for(j=0;j<len;j++){ //就一个子串,没必要直接上自动机...
if(dp[i][j]){
for(ite=mp.begin();ite!=mp.end();ite++){
fir=ite->first;
sec=ite->second;
if(fir==s[j+1])
dp[i+1][j+1]+=(dp[i][j]*sec);
else{
tt=j;
while(tt&&s[tt+1]!=fir)
tt=nex[tt];
if(s[tt+1]==fir)
tt++;
dp[i+1][tt]+=(dp[i][j]*sec);
}
}
}
}
}
ans=0;
for(i=1;i<=m;i++)
ans+=dp[i][len];
printf("%.2lf%%\n",ans*100);
}
return 0;
}
相关文章推荐
- 51nod 动态规划入门
- 解决Windows与Ubuntu双系统时间同步问题
- ThinkPHP框架表单验证
- 高级I/O函数
- 利用JQuery制作一个瀑布流
- 如何优化linux系统
- 《第一行代码》读书笔记(第五章,第六章)
- 数组中只出现一次的数字
- HYSBZ 2243 树链剖分
- NSCalendar + NSDateComponents
- UVA624 - CD (DFS)
- 中山培训 2016.7.11
- 在linux下查看内核版本、gcc版本、操作系统多少位等参数
- 数据结构中时间复杂度和空间复杂度的理解
- preparestatement可以避免注入
- 18大经典数据挖掘算法小结
- 运维脚本规范
- NKOI 1887 借教室
- LeetCode 171. Excel Sheet Column Number
- lua脚本对utf8字符串过滤中文字符