AC自动机+DP泛做
Posted 23forever
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC自动机+DP泛做相关的知识,希望对你有一定的参考价值。
情报加密
题意:给定\(n\)个字符串\(n(1<=n<=50)\)个长度小于&20&的模式串。在给定一个长度小于\(1000\)的字符串\(T\)。
求最少改变多少个\(T\)中的字符,使得\(T\)中不包含\(n\)个模式串。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define min(a, b) (a < b ? a : b)
const int CHA = 4;
const int MAXN = 1000;
const int INF = 0x3f3f3f3f;
using namespace std;
struct AcAutoMaton {
int tot, trie[MAXN + 5][4], fail[MAXN + 5], dp[MAXN + 5][MAXN + 5];
bool val[MAXN + 5];
queue < int > Q;
AcAutoMaton() {
tot = 0;
}
void insert(char *P) {
int l = strlen(P), now = 0;
for (int i = 0; i < l; ++i) {
int c = P[i] - ‘A‘;
if (!trie[now][c]) trie[now][c] = ++tot;
now = trie[now][c];
}
val[now] = true;
}
void getFail() {
for (int i = 0; i < CHA; ++i) {
int u = trie[0][i];
if (u) {
fail[u] = 0;
Q.push(u);
}
}
while (!Q.empty()) {
int cur = Q.front();
Q.pop();
for (int i = 0; i < CHA; ++i) {
int u = trie[cur][i];
if (u) {
fail[u] = trie[fail[cur]][i];
val[u] |= val[fail[u]];
Q.push(u);
}
else
trie[cur][i] = trie[fail[cur]][i];
}
}
}
int query(char *T) {
int l = strlen(T);
memset(dp, 0x3f, sizeof(dp));
dp[0][0] = 0;
for (int i = 1; i <= l; ++i)
for (int j = 0; j <= tot; ++j)
for (int k = 0; k < CHA; ++k) {
int u = trie[j][k];
if (!val[u]) {
if (T[i - 1] - ‘A‘ == k)
dp[i][u] = min(dp[i][u], dp[i - 1][j]);
else
dp[i][u] = min(dp[i][u], dp[i - 1][j] + 1);
}
}
int ret = INF;
for (int j = 0; j <= tot; ++j)
ret = min(ret, dp[l][j]);
return ret == INF ? -1 : ret;
}
}AC;
int n;
char P[20 + 5];
void init() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%s", P);
AC.insert(P);
}
AC.getFail();
}
char T[1000 + 5];
int main() {
init();
scanf("%s", T);
printf("%d\n", AC.query(T));
return 0;
}
以上是关于AC自动机+DP泛做的主要内容,如果未能解决你的问题,请参考以下文章
HDU4057 Rescue the Rabbit(AC自动机+状压DP)
Codeforces 86C Genetic engineering(AC自动机+DP)