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

POJ 3691 DNA repair ( Trie图 && DP )

时间:2017-10-11 23:38:12      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:isp   src   max   font   include   closed   tab   state   blog   

题意 : 给出 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\n", ans);
        else puts("-1");
    }
    return 0;
}
View Code

 

POJ 3691 DNA repair ( Trie图 && DP )

标签:isp   src   max   font   include   closed   tab   state   blog   

原文地址:http://www.cnblogs.com/Rubbishes/p/7653247.html

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