题意:训练指南P217
分析:没有模板串也就是在自动机上走L步,不走到val[u] == v的节点的概率
PS:边读边insert WA了,有毒啊!
#include <bits/stdc++.h> using namespace std; const int K = 20 + 5; const int L = 100 + 5; const int NODE = K * K; const int SIZE = 66; int idx[256], n; struct AC { int ch[NODE][SIZE], fail[NODE], match[NODE], sz; void clear(void) { memset (ch[0], 0, sizeof (ch[0])); sz = 1; } void insert(char *P) { int u = 0, lenp = strlen (P); for (int c, i=0; i<lenp; ++i) { c = idx[P[i]]; if (!ch[u][c]) { memset (ch[sz], 0, sizeof (ch[sz])); match[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } match[u] = 1; } void build(void) { queue<int> que; fail[0] = 0; int u; for (int c=0; c<SIZE; ++c) { u = ch[0][c]; if (u) { fail[u] = 0; que.push (u); } } while (!que.empty ()) { int r = que.front (); que.pop (); for (int c=0; c<SIZE; ++c) { int u = ch[r][c]; if (!u) { ch[r][c] = ch[fail[r]][c]; continue; } que.push (u); int v = fail[r]; while (v && !ch[v][c]) v = fail[v]; fail[u] = ch[v][c]; match[u] |= match[fail[u]]; } } } }ac; double prob[SIZE]; bool vis[NODE][L]; double dp[NODE][L]; double DFS(int u, int len) { if (!len) return 1.0; if (vis[u][len]) return dp[u][len]; vis[u][len] = true; double &ret = dp[u][len]; ret = 0; for (int i=0; i<n; ++i) { if (!ac.match[ac.ch[u][i]]) ret += prob[i] * DFS (ac.ch[u][i], len - 1); } return ret; } char pattern[30][30]; //char pattern[30]; int main(void) { int T, cas = 0; scanf ("%d", &T); while (T--) { //char pattern[30]; ac.clear (); int k; scanf ("%d", &k); for (int i=1; i<=k; ++i) { scanf ("%s", &pattern[i]); //scanf ("%s", &pattern); //ac.insert (pattern); } //ac.build (); scanf ("%d", &n); char str[3]; for (int i=0; i<n; ++i) { scanf ("%s%lf", &str, &prob[i]); idx[str[0]] = i; } for (int i=1; i<=k; ++i) ac.insert (pattern[i]); ac.build (); int len; scanf ("%d", &len); memset (vis, false, sizeof (vis)); printf ("Case #%d: %.6lf ", ++cas, DFS (0, len)); } return 0; }