AC automaton + DP pan-do

intelligence encryption

Question meaning: Given \(n\) strings \(n(1<=n<=50)\) pattern strings whose length is less than &20&. Given a string \(T\ ) whose length is less than \(1000\ ) . Find the minimum number of characters in \(T\) that are changed so that \(T\) does not contain \(n\) patterns.

AC code:

#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;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325225962&siteId=291194637