UVA 11468 - Substring
题意:给定一些模式串,然后给出一些字母出现的概率,每次随机出现一个字母,要求出这些字母出现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;
}