zoukankan      html  css  js  c++  java
  • POJ 3691 DNA repair ( Trie图 && DP )

    题意 : 给出 n 个病毒串,最后再给出一个主串,问你最少改变主串中的多少个单词才能使得主串中不包含任何一个病毒串

    分析 : 做多了AC自动机的题,就会发现这些题有些都是很套路的题目。在构建 Trie 图的时候给病毒串末尾打上标记,最后定义DP[i][j] = 长度为 i 的串在 j 这个状态节点最少改变数使得其不包含病毒串,则状态转移方程

    if(Trie[k]不是被标记的病毒节点) DP[i+1][j] = min( DP[i+1][j], DP[i][k] + (mp[S[i]] != k) )

    k 为 j 节点的四个下一状态,转到"ATGC"其中一个,而mp[]作用是把"ATGC"转为0、1、2、3

    DP的初始状态为 DP[0][0] = 0,DP[0~len][0~节点数] = INF

    具体的看代码即可

    #include<queue>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    const int Max_Tot = 1111;
    const int Letter  = 4;
    const int INF = 0x3f3f3f3f;
    int mp[128];
    
    struct Aho{
        struct StateTable{
            int Next[Letter];
            int fail, flag;
        }Node[Max_Tot];
        int Size;
        queue<int> que;
    
        inline void init(){
            while(!que.empty()) que.pop();
            memset(Node[0].Next, 0, sizeof(Node[0].Next));
            Node[0].fail = Node[0].flag = 0;
            Size = 1;
        }
    
        inline void insert(char *s){
            int now = 0;
            for(int i=0; s[i]; i++){
                int idx = mp[s[i]];
                if(!Node[now].Next[idx]){
                    memset(Node[Size].Next, 0, sizeof(Node[Size].Next));
                    Node[Size].fail = Node[Size].flag = 0;
                    Node[now].Next[idx] = Size++;
                }
                now = Node[now].Next[idx];
            }
            Node[now].flag = 1;
        }
    
        inline void BuildFail(){
            Node[0].fail = 0;
            for(int i=0; i<Letter; i++){
                if(Node[0].Next[i]){
                    Node[Node[0].Next[i]].fail = 0;
                    que.push(Node[0].Next[i]);
                }else Node[0].Next[i] = 0;///必定指向根节点
            }
            while(!que.empty()){
                int top = que.front(); que.pop();
                if(Node[Node[top].fail].flag) Node[top].flag = 1;
                for(int i=0; i<Letter; i++){
                    int &v = Node[top].Next[i];
                    if(v){
                        que.push(v);
                        Node[v].fail = Node[Node[top].fail].Next[i];
                    }else v = Node[Node[top].fail].Next[i];
                }
            }
        }
    }ac;
    char S[1111];
    int dp[1111][1111];
    
    int main(void)
    {
        mp['A'] = 0,
        mp['T'] = 1,
        mp['G'] = 2,
        mp['C'] = 3;
        int n, Case = 1;
        while(~scanf("%d", &n) && n){
            ac.init();
            for(int i=0; i<n; i++){
                scanf("%s", S);
                ac.insert(S);
            }
            ac.BuildFail();
            scanf("%s", S);
            int len = strlen(S);
    
            for(int i=0; i<=len; i++)
                for(int j=0; j<=ac.Size; j++)
                    dp[i][j] = 2333;
    
            dp[0][0] = 0;
    
            for(int i=0; i<len; i++){
                for(int j=0; j<ac.Size; j++){
                    if(dp[i][j] != 2333){
                        for(int k=0; k<4; k++){
                            int newi = i+1;
                            int newj = ac.Node[j].Next[k];
                            if(!ac.Node[newj].flag){
                                dp[newi][newj] = min(dp[newi][newj],
                                                     dp[i][j] + (k != mp[S[i]]) );
                            }
                        }
                    }
                }
            }
    
            int ans = 2333;
            for(int i=0; i<ac.Size; i++)
                ans = min(ans, dp[len][i]);
    
            printf("Case %d: ", Case++);
            if(ans != 2333) printf("%d
    ", ans);
            else puts("-1");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    文本框设置只读,后台可获取
    div 在同一行的 CSS处理
    在标签中添加属性
    (转)如何使用SignalTap II觀察reg與wire值? (SOC) (Verilog) (Quartus II) (SignalTap II)
    (转)如何使用ModelSim對Megafunction或LPM作仿真? (SOC) (MegaCore) (ModelSim)
    (笔记)TSL235新型光感器件强烈推荐使用
    (转)如何增加SignalTap II能觀察的reg與wire數量? (SOC) (Quartus II) (SignalTap II)
    (转) 如何將10進位轉2進位? (C/C++) (C)
    (转)如何使用ModelSim作前仿真與後仿真? (SOC) (Quartus II) (ModelSim)
    (笔记)关于LM3S片内FLASH编程的一点建议
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7653247.html
Copyright © 2011-2022 走看看