POJ 3691 DNA repair ( Trie图 && DP )

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n", ans);
        else puts("-1");
    }
    return 0;
}
View Code

 

以上是关于POJ 3691 DNA repair ( Trie图 && DP )的主要内容,如果未能解决你的问题,请参考以下文章

18.10.29 POJ 3691 DNA repair(AC自动机+dp)

POJ 3691 DNA repair ( Trie图 && DP )

HDU2457 DNA repair(AC自动机+DP)

HDU 2457:DNA repair

DNA repair HDU - 2457 AC鑷姩鏈?DP

HDU 2457 DNA repair AC自动机 + dp