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)

POJ3691DNA repair(AC自动机,DP)

Codeforces 86C Genetic engineering(AC自动机+DP)

POJ1699 Best Sequence(AC自动机+状压DP)

HDU2457 DNA repair(AC自动机+DP)

背包DP泛做