zoukankan      html  css  js  c++  java
  • HDU 2457 POJ 3691 DNA repair(AC自动机+DP)

    (n)个模式串和一个串(s),要求修改(s)最少的字符使得没有一个模式串是(s)的子串


    (dp[i][j])表示长度为(i),到达(AC)自动机的节点(j)所需修改的最少字符数量

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2000;
    struct Trie{
        int next[maxn][26], fail[maxn], end[maxn];
        int dp[maxn][maxn];
        int last[maxn];
        int root, L;
        int newnode(){
            for (int i = 0; i < 26; i++)
                next[L][i] = -1;
            fail[L]=last[L]=end[L]=0;
            return L++;
        }
        void init(){
            L = 0;
            root = newnode();
        }
        void insert(char buf[]){
            int len = strlen(buf);
            int now = root;
            for(int i=0;i<len;i++){
                if(next[now][buf[i]-'A'] == -1) 
                    next[now][buf[i]-'A'] = newnode();
                now = next[now][buf[i]-'A'];
            }
            end[now]++;
        }
        void build(){
            queue<int>Q;
            fail[root]=root;
            for(int i = 0;i < 26;i++){
                if(next[root][i]==-1)
                    next[root][i]=root;
                else{
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while(!Q.empty()){
                int now = Q.front();
                Q.pop();
                end[now]+=end[fail[now]];
                for(int i = 0;i < 26;i++){
                    if(next[now][i] == -1) 
                        next[now][i] = next[fail[now]][i];
                    else{
                        int son=next[now][i];
                        fail[son]=next[fail[now]][i];
                        last[son]=end[fail[son]]?fail[son]:last[fail[son]];
                        Q.push(next[now][i]); 
                    }  
                }
            }
        }
        char to[4]={'A','G','C','T'};
        void solve(char s[]){
            memset(dp,0x3f,sizeof(dp));
            dp[0][0]=0;
            int n=strlen(s);
            for(int i=1;i<=n;i++){
                for(int j=0;j<L;j++){
                    if(end[j]||dp[i-1][j]==0x3f3f3f3f)continue;
                    for(char k:to){
                        int son=next[j][k-'A'];
                        if(!end[son])
                            dp[i][son]=min(dp[i][son],dp[i-1][j]+(s[i-1]!=k));
                    }
                }
            }
            int ans=0x3f3f3f3f;
            for(int i=0;i<L;i++)
                ans=min(ans,dp[n][i]);
            if(ans==0x3f3f3f3f)ans=-1;
            printf("%d
    ",ans);
        }
    }ac;
    
    char s[maxn];
    int main(){
        int n,_=0;
        while(scanf("%d",&n)&&n){
            ac.init();
            for(int i=0;i<n;i++){
                scanf("%s",s);
                ac.insert(s);
            }
            ac.build();
            scanf("%s",s);
            printf("Case %d: ",++_);
            ac.solve(s);
        }
        return 0;
    }
    
  • 相关阅读:
    P1121 环状最大两段子段和
    无题
    cdoj 1485 柱爷搞子串 sam treap
    自然数幂和
    Gym 100341C AVL Trees NTT
    线性筛分解质因子
    codeforces 366 Ant Man dp
    UVALive 6914 Maze Mayhem 轮廓线dp
    hdu 5790 Prefix 字典树 主席树
    莫比乌斯反演个人小结
  • 原文地址:https://www.cnblogs.com/Zeronera/p/13726843.html
Copyright © 2011-2022 走看看