HDU 2457 DNA repair(AC自动机 + DP)题解

题意:n个病毒串,给你一个串t,问你最少改几个能没有病毒串

思路:去年还觉得挺难得...其实就是AC自动机上跑一下简单的DP,每个位置都往没病毒的地方跑,然后看一下最少是什么。

代码:

#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1000 + 5;
const int M = 50 + 5;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 20090717;
int n, m;
int dp[maxn][maxn];
int getid(char s){
    if(s == ‘A‘) return 0;
    if(s == ‘C‘) return 1;
    if(s == ‘G‘) return 2;
    return 3;
}
struct Aho{
    struct state{
        int next[4];
        int fail, cnt;
    }node[maxn];
    int size;
    queue<int> q;

    void init(){
        size = 0;
        newtrie();
        while(!q.empty()) q.pop();
    }

    int newtrie(){
        memset(node[size].next, 0, sizeof(node[size].next));
        node[size].cnt = node[size].fail = 0;
        return size++;
    }

    void insert(char *s){
        int len = strlen(s);
        int now = 0;
        for(int i = 0; i < len; i++){
            int c = getid(s[i]);
            if(node[now].next[c] == 0){
                node[now].next[c] = newtrie();
            }
            now = node[now].next[c];
        }
        node[now].cnt = 1;
    }

    void build(){
        node[0].fail = -1;
        q.push(0);

        while(!q.empty()){
            int u = q.front();
            q.pop();
            if(node[node[u].fail].cnt && u) node[u].cnt = 1;
            for(int i = 0; i < 4; i++){
                if(!node[u].next[i]){
                    if(u == 0)
                        node[u].next[i] = 0;
                    else
                        node[u].next[i] = node[node[u].fail].next[i];
                }
                else{
                    if(u == 0) node[node[u].next[i]].fail = 0;
                    else{
                        int v = node[u].fail;
                        while(v != -1){
                            if(node[v].next[i]){
                                node[node[u].next[i]].fail = node[v].next[i];
                                break;
                            }
                            v = node[v].fail;
                        }
                        if(v == -1) node[node[u].next[i]].fail = 0;
                    }
                    q.push(node[u].next[i]);
                }
            }
        }
    }

    void query(char *s){
        int len = strlen(s);

        for(int i = 0; i <= len; i++){
            for(int j = 0; j < size; j++){
                dp[i][j] = INF;
            }
        }
        dp[0][0] = 0;
        for(int i = 0; i < len; i++){
            for(int j = 0; j < size; j++){
                if(dp[i][j] == INF) continue;
                for(int k = 0; k < 4; k++){
                    if(node[node[j].next[k]].cnt) continue;
                    if(getid(s[i]) != k) dp[i + 1][node[j].next[k]] = min(dp[i + 1][node[j].next[k]], dp[i][j] + 1);
                    else dp[i + 1][node[j].next[k]] = min(dp[i + 1][node[j].next[k]], dp[i][j]);
                }
            }
        }
        int ans = INF;
        for(int i = 0; i < size; i++)
            if(node[i].cnt == 0) ans = min(ans, dp[len][i]);
        if(ans == INF) printf("-1\n");
        else printf("%d\n", ans);
    }

}ac;
char s[1005];
int main(){
    int ca = 1;
    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: ", ca++);
        ac.query(s);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/KirinSB/p/11190991.html

时间: 2024-08-04 08:02:16

HDU 2457 DNA repair(AC自动机 + DP)题解的相关文章

HDU 2457 DNA repair AC自动机 + dp

http://acm.hdu.edu.cn/showproblem.php?pid=2457 首先把病毒串保存一下,然后对于每一个trie上的节点,跑一发AC自动机,建立一个trie图. 建立的时候,对应做一些修改. 比如,现在建立成了这个样子. 如果he是一个病毒串,那么应该相对应的,把she那个he的位置,标志上,它也是病毒串,也就是不能转移到这一个状态. 这个可以在buildfail的时候对应修改. dp, 设dp[i][j],表示处理到字符串的第i个,走到了AC自动机的第j个节点,变成了

POJ 3691 &amp; HDU 2457 DNA repair (AC自动机,DP)

http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5690   Accepted: 2669 Description Biologists finally invent techniques of repairing DNA that contain

POJ 3691 &amp;amp; HDU 2457 DNA repair (AC自己主动机,DP)

http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5690   Accepted: 2669 Description Biologists finally invent techniques of repairing DNA that contain

POJ 3691 DNA repair AC自动机 + DP

题意:给你只包含‘A’,‘G’,‘T’,‘C’四个字母的n个模板串和1个文本串,问你文本串改变多少个字符就可以使得文本串中没有一个模板串 解题思路: 我们可以知道  dp[i][j] 为文本串到 第i 个字符  AC自动机状态为j的最少的变换次数(这里为什么要用AC自动机,因为end数组可以记录哪一个状态是结束的,而且处理以后可以知道那些后缀等于前缀--也就是不能到达,因为如果能够到达的话那么状态更新就会产生错误.),这样dp即可 解题代码: 1 // File Name: temp.cpp 2

hdu 2825 Wireless Password(ac自动机&amp;dp)

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4022    Accepted Submission(s): 1196 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

HDU 2457 DNA repair (AC自动机 + DP)

题目链接:DNA repair 解析:给出n个致病DNA序列,给一段DNA片段,问最少修改多少个碱基才能修复这段DNA序列中的所有致病序列. AC自动机 + DP. 将n个致病DNA序列构成一个自动机. 令DP[i][j]表示长度为i走到节点j是所需改变的最少个数. 状态转移时,枚举下一步所有可能的碱基,然后判断该碱基是否达到匹配状态,若能,则安全转移,继续枚举下一个碱基:否则在不匹配的前提下,看该碱基加入之后是否跟上一状态相同,若不同,则需修复,即计数加一.若相同,直接转移即可.然后选择其中最

[AC自动机+dp] hdu 2457 DNA repair

题意: 给N个单词,再给一个串str (只含A.G.C.T) 问对于str要至少修改几个字符能不含有N个单词 思路: 建立trie图,做自动机dp dp[i][j] 代表走过str的i个字母在j节点至少需要修改几个字符 trie *p=node[j]->next[k]; if(p->mark) continue; //不可达 dp[i][p->id]=min(dp[i][p->id],dp[i-1][j]+(getid(fuck[i])!=k)); 就是第i步从节点j走到对应的k,

HDU - 2457 DNA repair

Description Biologists finally invent techniques of repairing DNA that contains segments causing kinds of inherited diseases. For the sake of simplicity, a DNA is represented as a string containing characters 'A', 'G' , 'C' and 'T'. The repairing tec

poj3691--DNA repair(AC自动机+dp)

DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5743   Accepted: 2693 Description Biologists finally invent techniques of repairing DNA that contains segments causing kinds of inherited diseases. For the sake of simplicity, a

HDU 2825 Wireless Password AC自动机+dp

训练赛第二场的I题,上完体育课回来就把这题过了,今天训练赛rank1了,还把大大队虐了,而且我还过了这道题 (虽然我也就过了这道题...),第一次在比赛中手写AC自动机还带dp的,心情大好. 给一个字符串集合,求包含该集合超过K个字符的,长度为L的字符串的个数. 显然是在AC自动机上跑dp,设dp[u][L][k]表示当前在结点u,还要走L步,当前状态为k的个数.一开始第三维表示的是包含k个字符串,但是题目要求不含重复的,那就只能状压了.转移为dp[u][L][k]+=dp[v][L-1][nk