11468 Substring (AC自動機 + 概率dp)
阿新 • • 發佈:2018-12-24
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <vector> #include <map> #include <queue> using namespace std; int get(char ch){ if (ch >= 'a' && ch <= 'z'){ return ch - 'a'; } if (ch >= 'A' && ch <= 'Z'){ return ch - 'A' + 26; } if (ch >= '0' && ch <= '9'){ return ch - '0' + 52; } } const int maxn = 500; const int maxm = 62; char cmd[50]; double mp[128]; struct Trie{ int L, root; int next[maxn][maxm]; int fail[maxn]; int flag[maxn]; double dp[101][maxn]; void init(){ L = 0; root = newnode(); } void insert(char* s){ int len = strlen(s); int nod = root; for (int i = 0; i < len; ++i){ int id = get(s[i]); if (next[nod][id] == -1){ next[nod][id] = newnode(); } nod = next[nod][id]; } flag[nod] = 1; } int newnode(){ for (int i = 0; i < maxm; ++i){ next[L][i] = -1; } flag[L] = 0; return L++; } void bfs(){ queue<int>q; fail[root] = root; for (int i = 0; i < maxm; ++i){ if (next[root][i] == -1){ next[root][i] = root; } else { fail[next[root][i] ] = root; q.push(next[root][i]); } } while(!q.empty()){ int u = q.front(); q.pop(); flag[u] |= flag[fail[u] ]; for (int i = 0; i < maxm; ++i){ if (next[u][i] == -1){ next[u][i] = next[fail[u] ][i]; } else { fail[next[u][i] ] = next[fail[u] ][i]; q.push(next[u][i]); } } } } void solve(int n){ memset(dp,0,sizeof dp); dp[0][0] = 1.0; for (int i = 1; i <= n; ++i){ for (int j = 0; j < L; ++j){ if (dp[i-1][j] == 0) continue; for (int k = 0; k < maxm; ++k){ int nx = next[j][k]; if (flag[nx]) continue; dp[i][nx] += dp[i-1][j] * mp[k]; } } } double ans = 0; for (int i = 0; i < L; ++i){ ans += dp[n][i]; } printf("%.6f\n", ans); } }ac; int main(){ int T; int ks = 0; scanf("%d",&T); while(T--){ int n; scanf("%d", &n); memset(mp,0,sizeof mp); ac.init(); for (int i = 0; i < n; ++i){ scanf("%s", cmd); ac.insert(cmd); } ac.bfs(); scanf("%d", &n); for (int i = 0; i < n; ++i){ double x; scanf("%s%lf", cmd, &x); mp[get(cmd[0]) ] = x; } scanf("%d", &n); printf("Case #%d: ", ++ks); ac.solve(n); } return 0; }