HDU 3689 Infinite monkey theorem ——(自动机+DP)

  这题由于是一个单词,其实直接kmp+dp也无妨。建立自动机当然也是可以的。设dp[i][j]表示匹配到第i个字母的时候,在单词中处于第j个位置的概率,因此最终的答案是dp[0~m][len],m是输入的长度,len是单词的长度。转移方程见代码,即在一个节点的位置时,枚举下一步的走法,乘以这种走法的概率即是对下一个状态的概率贡献。

  其实自动机的fail指针跳转的位置即是kmp中nxt数组跳转的位置。

  代码如下:

 1     {
 2         while(j && word[j+1] != word[i]) j = nxt[j];
 3         if(word[j+1] == word[i]) j++;
 4         nxt[i] = j;
 5     }
 6 }
 7 
 8 int main()
 9 {
10     while(scanf("%d%d",&n,&m) == 2)
11     {
12         if(n==0 && m==0) break;
13         char s[5];
14         for(int i=1;i<=n;i++)
15         {
16             scanf("%s%lf",s,p+i);
17             c[i] = s[0];
18         }
19         scanf("%s",word+1);
20         len = strlen(word+1);
21         get_nxt();
22         memset(dp,0,sizeof dp);
23         dp[0][0] = 1.0;
24         for(int i=0;i<m;i++)
25         {
26             for(int j=0;j<len;j++)
27             {
28                 for(int k=1;k<=n;k++)
29                 {
30                     int pos = j;
31                     while(pos && word[pos+1] != c[k]) pos = nxt[pos];
32                     if(word[pos+1] == c[k]) pos++;
33                     dp[i+1][pos] += dp[i][j] * p[k];
34                 }
35             }
36         }
37         double ans = 0.0;
38         for(int i=0;i<=m;i++) ans += dp[i][len];
39         printf("%.2f%%\n",ans*100.0);
40     }
41     return 0;
42 }
kmp+dp
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int MAX_Tot = 100 + 50;
  4 
  5 int n,m,len;
  6 double p[30];
  7 char word[20];
  8 int nxt[20];
  9 double dp[1005][20];
 10 
 11 struct Aho
 12 {
 13     struct state
 14     {
 15         int nxt[26];
 16         int fail,cnt;
 17     }stateTable[MAX_Tot];
 18 
 19     int size;
 20 
 21     queue<int> que;
 22 
 23     void init()
 24     {
 25         while(que.size()) que.pop();
 26         for(int i=0;i<MAX_Tot;i++)
 27         {
 28             memset(stateTable[i].nxt,0,sizeof(stateTable[i].nxt));
 29             stateTable[i].fail = stateTable[i].cnt = 0;
 30         }
 31         size = 1;
 32     }
 33 
 34     void insert(char *s)
 35     {
 36         int n = strlen(s);
 37         int now = 0;
 38         for(int i=0;i<n;i++)
 39         {
 40             char c = s[i];
 41             if(!stateTable[now].nxt[c-'a'])
 42                 stateTable[now].nxt[c-'a'] = size++;
 43             now = stateTable[now].nxt[c-'a'];
 44         }
 45         stateTable[now].cnt++;
 46     }
 47 
 48     void build()
 49     {
 50         stateTable[0].fail = -1;
 51         que.push(0);
 52 
 53         while(que.size())
 54         {
 55             int u = que.front();que.pop();
 56             for(int i=0;i<26;i++)
 57             {
 58                 if(stateTable[u].nxt[i])
 59                 {
 60                     if(u == 0) stateTable[stateTable[u].nxt[i]].fail = 0;
 61                     else
 62                     {
 63                         int v = stateTable[u].fail;
 64                         while(v != -1)
 65                         {
 66                             if(stateTable[v].nxt[i])
 67                             {
 68                                 stateTable[stateTable[u].nxt[i]].fail = stateTable[v].nxt[i];
 69                                 break;
 70                             }
 71                             v = stateTable[v].fail;
 72                         }
 73                         if(v == -1) stateTable[stateTable[u].nxt[i]].fail = 0;
 74                     }
 75                     que.push(stateTable[u].nxt[i]);
 76                 }
 77                 /*****建立自动机nxt指针*****/
 78                 else
 79                 {
 80                     if(u == 0) stateTable[u].nxt[i] = 0;
 81                     else
 82                     {
 83                         int p = stateTable[u].fail;
 84                         while(p != -1 && stateTable[p].nxt[i] == 0) p = stateTable[p].fail;
 85                         if(p == -1) stateTable[u].nxt[i] = 0;
 86                         else stateTable[u].nxt[i] = stateTable[p].nxt[i];
 87                     }
 88                 }
 89                 /*****建立自动机nxt指针*****/
 90             }
 91         }
 92     }
 93 }aho;
 94 
 95 int main()
 96 {
 97     while(scanf("%d%d",&n,&m) == 2)
 98     {
 99         if(n==0 && m==0) break;
100         aho.init();
101         char s[5];
102         memset(p,0,sizeof p);
103         for(int i=1;i<=n;i++)
104         {
105             double t;
106             scanf("%s%lf",s,&t);
107             p[s[0]-'a'] = t;
108         }
109         scanf("%s",word+1);
110         aho.insert(word+1); aho.build();
111         memset(dp,0,sizeof dp);
112         dp[0][0] = 1.0;
113         int sz = aho.size-1;
114         for(int i=0;i<m;i++)
115         {
116             for(int j=0;j<sz;j++)
117             {
118                 for(int k=0;k<26;k++)
119                 {
120                     int v = aho.stateTable[j].nxt[k];
121                     dp[i+1][v] += dp[i][j] * p[k];
122                 }
123             }
124         }
125         double ans = 0.0;
126         for(int i=0;i<=m;i++) ans += dp[i][sz];
127         printf("%.2f%%\n",ans*100.0);
128     }
129     return 0;
130 }
自动机+dp

 

转载于:https://www.cnblogs.com/zzyDS/p/6295781.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值