题目链接: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
代码:
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <cmath> 5 #include <map> 6 #include <iterator> 7 #include <vector> 8 using namespace std; 9 typedef long long LL; 10 11 int next[20],n,m; 12 char str[20]; 13 double f[30],dp[1100][20]; 14 15 void get_next(int m,const char* str){ 16 int j = 0; 17 next[1] = 0; 18 for( int i=2;i<m;i++ ){ 19 while( j>0 && str[j+1]!=str[i] ) j = next[j]; 20 if( str[j+1] == str[i] ) j++; 21 next[i] = j; 22 } 23 } 24 25 int main(){ 26 while(scanf("%d%d",&n,&m)!=EOF){ 27 if( n==0&&m==0 ) break; 28 char c[2]; double d; 29 memset(f,0,sizeof(f)); 30 vector<int> v; 31 for(int i=0;i<n;i++){ 32 scanf("%s%lf",c,&d); 33 f[c[0]-‘a‘] = d; 34 v.push_back(c[0]-‘a‘); 35 } 36 scanf("%s",str+1); 37 int len = strlen(str+1); 38 memset(next,0,sizeof(next)); 39 get_next(len,str); 40 memset(dp,0,sizeof(dp)); 41 dp[0][0] = 100; 42 for(int i=0;i<m;i++){ 43 for(int j=0;j<len;j++){ 44 for(int k=0;k<v.size();k++){ 45 int fa = j; 46 while( fa&&v[k]!=str[fa+1]-‘a‘ ) fa = next[fa]; 47 if( str[fa+1]-‘a‘==v[k] ) fa++; 48 dp[i+1][fa] += dp[i][j] * f[v[k]]; 49 } 50 } 51 } 52 double sum = 0; 53 for(int i=0;i<=m;i++) sum += dp[i][len]; 54 printf("%.2f%%\n",sum); 55 } 56 return 0; 57 }
或者说可以用矩阵来实现
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <cmath> 5 #include <map> 6 #include <iterator> 7 #include <vector> 8 using namespace std; 9 typedef long long LL; 10 11 int next[20],n,m; 12 char str[20]; 13 double f[30]; 14 15 void get_next(int m,const char* str){ 16 int j = 0; 17 next[1] = 0; 18 for( int i=2;i<=m;i++ ){ 19 while( j>0 && str[j+1]!=str[i] ) j = next[j]; 20 if( str[j+1] == str[i] ) j++; 21 next[i] = j; 22 } 23 } 24 25 struct Matrix{ 26 double m[20][20]; 27 Matrix(){ 28 memset(m,0,sizeof(m)); 29 } 30 Matrix operator*(const Matrix &a){ 31 Matrix res; 32 for(int i=0;i<20;i++){ 33 for(int j=0;j<20;j++){ 34 for(int k=0;k<20;k++){ 35 res.m[i][j] += m[i][k] * a.m[k][j]; 36 } 37 } 38 } 39 return res; 40 } 41 }; 42 43 Matrix pow_bin(Matrix x,int e){ 44 Matrix res; 45 for(int i=0;i<20;i++) res.m[i][i] = 1; 46 while( e ){ 47 if( e&1 ) res = res * x; 48 x = x*x; 49 e>>=1; 50 } 51 return res; 52 } 53 54 int main(){ 55 while(scanf("%d%d",&n,&m)!=EOF){ 56 if( n==0&&m==0 ) break; 57 char c[2]; double d; 58 vector<int> v; 59 memset(f,0,sizeof(f)); 60 for(int i=0;i<n;i++){ 61 scanf("%s%lf",c,&d); 62 f[c[0]-‘a‘] = d; 63 v.push_back(c[0]-‘a‘); 64 } 65 getchar(); 66 gets(str+1); 67 int len = strlen(str+1); 68 get_next(len,str); 69 Matrix ma; 70 for(int i=0;i<len;i++){ 71 for(int j=0;j<v.size();j++){ 72 int fa = i; 73 while( fa&&str[fa+1]-‘a‘!=v[j] ) fa = next[fa]; 74 if( str[fa+1]-‘a‘==v[j] ) fa++; 75 ma.m[i][fa] += f[v[j]]; 76 } 77 } 78 Matrix res = pow_bin(ma,m); 79 double ans = 0; 80 for(int i=0;i<len;i++){ 81 ans += res.m[0][i]; 82 } 83 printf("%.2f%%\n",100-ans*100); 84 } 85 return 0; 86 }
矩阵版本
时间: 2024-11-05 23:38:14