1. 程式人生 > 實用技巧 >HDU 2457 DNA repair AC自動機+dp

HDU 2457 DNA repair AC自動機+dp

調了1天,居然是我的AC自動機板子有問題。。。
這個板子是真的繁瑣

#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;
//AC自動機
struct Aho{
    struct state{
       int net[26];
       int fail,cnt;// fail失配指標,到這個點有多少個點結束
    }stateTable[N];

    int ac_size;

    queue<int> que;

    void init(){
        while(que.size()) que.pop();

        for(int i = 0; i < N; ++ i){
            memset(stateTable[i].net, 0, sizeof(stateTable[i].net));
            stateTable[i].fail = stateTable[i].cnt=0;
        }
        ac_size = 0;
    }

    //建立trie樹
    void ac_insert(char *S){
        int n = strlen(S);
        int now = 0;

        for(int i=0;i<n;++i){
            int si=mp[S[i]];
            if(!stateTable[now].net[si]){
                stateTable[now].net[si] = ++ ac_size;
            }
            now = stateTable[now].net[si];
        }
        stateTable[now].cnt = 1;
    }

    //建立fail指標
    void ac_build(){
        for(int i = 0; i < 4; ++ i){
            if(stateTable[0].net[i]) que.push(stateTable[0].net[i]);
        }
        while(que.size()){
            int p = que.front(); que.pop();
            for(int j = 0; j < 4; ++ j){
                int c = stateTable[p].net[j];
                if(!c) stateTable[p].net[j] = stateTable[stateTable[p].fail].net[j];
                else{
                    que.push(c);
                    stateTable[c].fail = stateTable[stateTable[p].fail].net[j];
                    stateTable[c].cnt |= stateTable[stateTable[c].fail].cnt;  
                }
            }
        }
    }

    //
    int ac_get(int u){
        int res=0;
        while(u){
            res+=stateTable[u].cnt;
            stateTable[u].cnt=0;
            u=stateTable[u].fail;
        }
        return res;
    }

    //計算
    int ac_match(char *S){
        int n =strlen(S);
        int res = 0, now = 0;
        for(int i=0;i<n;++i){
            int si=S[i]-'a';
            if(stateTable[now].net[si])
                now=stateTable[now].net[si];
            else{
                int p=stateTable[now].fail;
                while(p!=-1&&!stateTable[p].net[si])p = stateTable[p].fail;
                if(p==-1) now=0;
                else now=stateTable[p].net[si];
            }
            if(stateTable[now].cnt)
                res+=ac_get(now);
        } 
        return res;
    }
}aho;

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

int solve(){
    int len = strlen(s + 1);
    memset(dp, 0x3f, sizeof(dp));
    dp[0][0] = 0;
    for(int i = 1; i <= len; ++ i){
        for(int j = 0; j <= aho.ac_size; ++ j){
            for(int k = 0; k < 4; ++ k){
                int tp = aho.stateTable[j].net[k];
                if(aho.stateTable[tp].cnt) continue;
                dp[i][tp] = min(dp[i][tp], dp[i - 1][j] + (mp[s[i]] != k));
            }
        }
    }   
    res = INF;
    for(int j = 0; j <= aho.ac_size; ++ j){
        res = min(res, dp[len][j]);
    }
    if(res == INF) return -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.ac_insert(s);
        }
        aho.ac_build();
        scanf("%s",s + 1);
        printf("Case %d: %d\n",++ Case, solve());
    }
    return 0;
}