首页 > 技术文章 > HDU 2457 DNA repair AC自动机+dp

A-sc 2020-08-27 16:19 原文

调了1天,居然是我的AC自动机板子有问题。。。
这个板子是真的繁琐
8/27/21:16 已更新简洁版本

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<fstream>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 1e3 + 5;
const int mod = 998244353;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
bool cmp(int a, int b){return a > b;}
//

map<char, int>mp;
struct Aho{
    int nxt[N][30] ,fail[N], mark[N];
    int size;
    
    queue<int> que;
    void init(){
        while(que.size()) que.pop();
        memset(nxt, 0, sizeof(nxt));
        memset(fail, 0, sizeof(fail));
        memset(mark, 0, sizeof(mark));
        size = 0;
    }
    
    //建立trie树
    void Insert(char *S){
        int n = strlen(S);
        int now = 0;
        for(int i = 0; i < n; ++ i){
            int id = mp[S[i]];
            if(!nxt[now][id]) nxt[now][id] = ++ size;
            now = nxt[now][id];
        }
        mark[now] = 1;
    }
    
    //建立fail指针
    void Build(){
        fail[0] = -1;
        for(int i = 0; i < 4; ++ i){
            if(nxt[0][i]) que.push(nxt[0][i]);
        }
        
        while(que.size()){
            int u = que.front(); que.pop();
            for(int j = 0; j < 4; ++ j){
                int v = nxt[u][j];
                if(!v) nxt[u][j] = nxt[fail[u]][j];
                else{
                    que.push(v);
                    fail[v] = nxt[fail[u]][j];
                    mark[v] |= mark[fail[v]];
                }
            }
        }
    }
}aho;


int T,n;
char s[N];
int dp[N][N], res, Case = 0;

int solve(){
    n = strlen(s + 1);
    memset(dp, 0x3f, sizeof(dp));
    dp[0][0] = 0;
    for(int i = 1; i <= n; ++ i){
        for(int j = 0; j <= aho.size; ++ j){
            for(int k = 0; k < 4; ++ k){
                int v = aho.nxt[j][k];
                if(aho.mark[v]) continue;
                dp[i][v] = min(dp[i][v], dp[i - 1][j] + (mp[s[i]] != k)); 
            }
        }
    }
    
    res = INF;
    for(int i = 0; i <= aho.size; ++ i){
        res = min(res, dp[n][i]);
    }
    if(res == INF) res = -1;
    return res;
}

int main()
{
    mp['A'] = 0, mp['T'] = 1, mp['G'] = 2, mp['C'] = 3; 
    while(~scanf("%d",&n) && n){
        aho.init();
        for(int i = 1; i <= n; ++ i){
            scanf("%s",s);
            aho.Insert(s);
        }
        aho.Build();
        scanf("%s",s + 1);
        printf("Case %d: %d\n",++ Case, solve());
    }
    return 0;
}

推荐阅读