题目链接:
http://acm.split.hdu.edu.cn/showproblem.php?pid=3689
题解:
kmp+概率dp
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
const int maxn = 1000+10;
struct node
{
char word;
double p;
}w[maxn];
double dp[maxn][30];
int Next[maxn];
char s[maxn];
int len=0;
void getNext()
{
int i=0,j=-1;
Next[0]=-1;
while(i!=len)
{
if(j==-1||s[i]==s[j])
{
++i,++j;
Next[i]=j;
}
else
j=Next[j];
}
}
int getpos(int pos,int k)
//通过kmp找到上一个和当前串匹配的相同的位置,找到就返回位置,不然就跟0,1的位置去比较
{
while(pos!=-1&&s[pos]!=w[k].word)
pos=Next[pos];
return pos+1;
}
// 按m次,长度为len的匹配串,有n种变换
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF&&(n+m))
{
char ss[maxn];
double p;
for(int i=0;i<n;i++)
{
scanf("%s%lf",ss,&p);
w[i].word=ss[0];
w[i].p=p;
}
scanf("%s",s);
len=(int)strlen(s);
met(dp,0);
getNext();
dp[0][0]=1.0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=len;j++)
for(int k=0;k<n;k++)
dp[i][getpos(j-1,k)]+=dp[i-1][j-1]*w[k].p;
}
double ans=0;
for(int i=1;i<=m;i++)
ans+=dp[i][len];
printf("%.2f%%\n",ans*100);
}
}