码迷,mamicode.com
首页 > 其他好文 > 详细

AC自动机+DP泛做

时间:2018-05-03 22:08:55      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:AC   else   for   queue   amp   ems   cpp   source   trie   

情报加密

题意:给定\(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泛做

标签:AC   else   for   queue   amp   ems   cpp   source   trie   

原文地址:https://www.cnblogs.com/23forever/p/8987372.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!