题意:给定一些模式串,然后给出一些字母出现的概率,每次随机出现一个字母,要求出这些字母出现L个组成的字符串不包含(即不是它的连续字串)已有模式串的概率
思路:AC自动机,先构造出AC自动机,构造的时候利用next数组的特性,记录下每个位置是否有经过一个单词结点,如果有这个结点就是不能走的结点,那么问题就变成了只能在能走的结点上走L步的概率,注意这里空边也要处理成可以走(走到它的next,因为不匹配的话就一直找到next能匹配的位置),然后进行dp即可
代码:
#include <cstdio> #include <cstring> #include <queue> using namespace std; const int MAXNODE = 405; const int SIGMA_SIZE = 62; struct AutoMac { int ch[MAXNODE][SIGMA_SIZE]; int val[MAXNODE]; int next[MAXNODE]; int sz; double dp[MAXNODE][105]; double p[SIGMA_SIZE]; bool vis[MAXNODE][105]; void init() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); val[0] = 0; memset(p, 0, sizeof(p)); memset(vis, false, sizeof(vis)); } int idx(char c) { if (c >= 'a' && c <= 'z') return c - 'a'; if (c >= 'A' && c <= 'Z') return c - 'A' + 26; if (c >= '0' && c <= '9') return c - '0' + 52; } void insert(char *s) { int n = strlen(s); int u = 0; for (int i = 0; i < n; i++) { int c = idx(s[i]); if (!ch[u][c]) { val[sz] = 0; memset(ch[sz], 0, sizeof(ch[sz])); ch[u][c] = sz++; } u = ch[u][c]; } val[u] = 1; } void getnext() { queue<int> Q; next[0] = 0; for (int c = 0; c < SIGMA_SIZE; c++) { int u = ch[0][c]; if (u) {next[u] = 0; Q.push(u);} } while (!Q.empty()) { int r = Q.front(); Q.pop(); for (int c = 0; c < SIGMA_SIZE; c++) { int u = ch[r][c]; if (!u) { ch[r][c] = ch[next[r]][c]; continue; } Q.push(u); int v = next[r]; while (v && !ch[v][c]) v = next[v]; next[u] = ch[v][c]; val[u] |= val[next[u]]; } } } double solve(int u, int L) { if (vis[u][L]) return dp[u][L]; vis[u][L] = true; if (!L) return dp[u][L] = 1; dp[u][L] = 0; for (int c = 0; c < SIGMA_SIZE; c++) { if (val[ch[u][c]]) continue; dp[u][L] += p[c] * solve(ch[u][c], L - 1); } return dp[u][L]; } }; AutoMac gao; int t, n, L; char str[25]; int main() { int cas = 0; scanf("%d", &t); while (t--) { gao.init(); scanf("%d", &n); while (n--) { scanf("%s", str); gao.insert(str); } gao.getnext(); scanf("%d", &n); while (n--) { scanf("%s", str); scanf("%lf", &gao.p[gao.idx(str[0])]); } scanf("%d", &L); printf("Case #%d: %.6lf\n", ++cas, gao.solve(0, L)); } return 0; }
UVA 11468 - Substring(AC自动机),布布扣,bubuko.com
原文:http://blog.csdn.net/accelerator_/article/details/38342807