题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串

思路:从昨天中午开始研究,研究到现在终于看懂了。既然是多模匹配,我们是要用到AC自动机的。我们把主串放到AC自动机上跑,并保证不出现模式串,这里对AC自动机的创建有所改动,我们需要修改不存在但是符合要求的节点,如果某节点的某一子节点不存在,我们就把这个子节点指向他父辈节点存在的该节点(比如k->next[1]不存在,k->fail->next[1]存在,我们就把他改为k->next[1] = k->fail->next[1]),因为只是在AC自动机上跑,我们只关心会不会匹配到模式串。这里要当心,如果一个节点的失配指向的是模式串尾,那么这个节点也就是模式串尾。我们用dp[i][j]去储存当前匹配到主串第i位,跑到AC自动机第j个状态的最小修改,状态转移方程dp[i + 1][j-next] = min(dp[i][j->next],dp[i][j]+str[i]!=k),每次我们都从上一个状态j开始搜索满足要求的下一个状态j->next。

参考:

[Pku 3691 1625] 字符串(四) {自动机应用}

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

代码:

#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define ll long long
const int maxn = 1000+5;
const int maxm = 100000+5;
const int MOD = 1e7;
const int INF = 0x3f3f3f3f;
const int kind = 4;
const char baset = 0;
using namespace std;
struct Trie{
    Trie *next[kind];
    Trie *fail;
    int flag;
    int id;
};
Trie *root,point[maxn];
queue<Trie*> Q;
int head,tail,idx;
int ID(char ch){
    if(ch == 'A') return 0;
    else if(ch == 'C') return 1;
    else if(ch == 'T') return 2;
    return 3;
}
Trie* NewNode(){
    Trie *temp = &point[idx];
    memset(temp ->next,NULL,sizeof(temp ->next));
    temp ->flag = 0;
    temp ->id = idx++;
    temp ->fail = NULL;
    return temp;
}

void Insert(char *s){
    Trie *p = root;
    for(int i = 0;s[i];i++){
        int x = ID(s[i]);
        if(p ->next[x] == NULL){
            p ->next[x] = NewNode();
        }
        p = p ->next[x];
    }
    p ->flag = 1;
}
void del(Trie *p){
    if(p == NULL) return;
    for(int i = 0;i < kind;i++){
        if(p ->next[i])
            del(p ->next[i]);
    }
    delete p;
}
void buildFail(){
    while(!Q.empty()) Q.pop();
    Q.push(root);
    Trie *p,*temp;
    while(!Q.empty()){
        temp = Q.front();
        Q.pop();
        for(int i = 0;i < kind;i++){
            if(temp ->next[i]){
                if(temp == root){
                    temp ->next[i] ->fail = root;
                }
                else{
                    p = temp ->fail;
                    while(p){
                        if(p ->next[i]){
                            temp ->next[i] ->fail = p ->next[i];
                            break;
                        }
                        p = p ->fail;
                    }
                    if(p == NULL) temp ->next[i] ->fail = root;
                }
                if(temp ->next[i] ->fail ->flag)
                    temp ->next[i] ->flag = 1;
                    //这里要注意,如果一个节点的失配指向的是模式串尾
                    //那么这个节点也就是模式串尾
                Q.push(temp ->next[i]);
            }
            else if(temp == root)
                temp ->next[i] = root;
                //root指向root,因为不存在这个子节点,没有限制
            else
                temp ->next[i] = temp ->fail ->next[i];
                //指向长辈节点存在的这个子节点
        }
    }
}
int dp[maxn][maxn << 1]; //主串匹配到第i个,在AC自动机上走到第j个节点
int solve(char *ch){
    int len = strlen(ch);
    for(int i = 0;i <= len;i++)
        for(int j = 0;j <= idx;j++)
            dp[i][j] = INF;
    dp[0][0] = 0;
    for(int i = 1;i <= len;i++){
        for(int j = 0;j < idx;j++){ //从这个状态j开始走,dp下一个状态
            if(point[j].flag) continue; //这个状态包含模式串
            if(dp[i - 1][j] == INF) continue;
            for(int k = 0;k < 4;k++){
                int r = point[j].next[k] ->id;  //下一个点
                if(point[r].flag) continue;     //下一个点包含模式串
                dp[i][r] = min(dp[i][r],dp[i - 1][j] + (ID(ch[i - 1]) != k));
            }
        }
    }
    int ans = INF;
    for(int i = 0;i < idx;i++){
        ans = min(ans,dp[len][i]);
    }
    if(ans == INF) return -1;
    else return ans;
}
char ch[1005];
int main(){
    int n,m,x,Case = 1;
    while(scanf("%d",&n) != EOF && n){
        idx = 0;
        root = NewNode();
        for(int i = 0;i < n;i++){
            scanf("%s",ch);
            Insert(ch);
        }
        buildFail();
        scanf("%s",ch);
        printf("Case %d: %d\n",Case++,solve(ch));
    }
    return 0;
}

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

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

    题意:给N个串,一个大串,要求在最小的改变代价下,得到一个不含上述n个串的大串. 思路:dp,f[i][j]代表大串中第i位,AC自动机上第j位的最小代价. #include<algorithm ...

  2. 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: ...

  3. HDU 2457/POJ 3691 DNA repair AC自动机+DP

    DNA repair Problem Description   Biologists finally invent techniques of repairing DNA that contains ...

  4. HDU2457 DNA repair —— AC自动机 + DP

    题目链接:https://vjudge.net/problem/HDU-2457 DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory ...

  5. [hdu2457]DNA repair(AC自动机+dp)

    题意:给出一些不合法的模式DNA串,给出一个原串,问最少需要修改多少个字符,使得原串中不包含非法串. 解题关键:多模式串匹配->AC自动机,求最优值->dp,注意在AC自动机上dp的套路. ...

  6. POJ 3691 DNA repair(AC自动机+DP)

    题目链接 能AC还是很开心的...此题没有POJ2778那么难,那个题还需要矩阵乘法,两个题有点相似的. 做题之前,把2778代码重新看了一下,回忆一下当时做题的思路,回忆AC自动机是干嘛的... 状 ...

  7. POJ3691 DNA repair(AC自动机 DP)

    给定N个长度不超过20的模式串,再给定一个长度为M的目标串S,求在目标串S上最少改变多少字符,可以使得它不包含任何的模式串 建立Trie图,求得每个节点是否是不可被包含的串,然后进行DP dp[i][ ...

  8. Hdu 2457 DNA repair (ac自己主动机+dp)

    题目大意: 改动文本串的上的字符,使之不出现上面出现的串.问最少改动多少个. 思路分析: dp[i][j]表示如今 i 个字符改变成了字典树上的 j 节点. 然后顺着自己主动机一直转移方程. 注意合法 ...

  9. hdu 4117 GRE Words AC自动机DP

    题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...

随机推荐

  1. [干货] 有了微信小程序,谁还学ReactNative?

    版权声明:本文由贺嘉原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/145 来源:腾云阁 https://www.qclou ...

  2. ios 的ASIHTTPRequest学习

    发起一个同步请求 同步意为着线程阻塞,在主线程中使用此方法会使应用Hang住而不响应任何用户事件.所以,在应用程序设计时,大多被用在专门的子线程增加用户体验,或用异步请求代替(下面会讲到). - (I ...

  3. Unity3D笔记四 基础知识概念

    1. Project视图 主要存放游戏中用到的所有资源文件,常见的包括:游戏脚本.预设.材质.动画.自定义字体.纹理.物理材质和GUI皮肤等. 1>     Folder: 文件夹,用于资源的分 ...

  4. 网络下载功能实现(downloader ) ---- HTML5+

    模块:downloader Downloader模块管理网络文件下载任务,用于从服务器下载各种文件,并支持跨域访问操作.通过plus.downloader获取下载管理对象.Downloader下载使用 ...

  5. oracle日常函数汇总(转载)

    第一篇 著名函数之单值函数 注:N表示数字型,C表示字符型,D表示日期型,[]表示内中参数可被忽略,fmt表示格式 数值类型函数 数值型函数输入数字型参数并返回数值型的值.多数该类函数的返回值支持38 ...

  6. kibana 和ES安装配置常见问题解决

    1.下载相同版本的kibana和ES: es5.6.5下载地址:https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5 ...

  7. Python大数据:外部数据获取(网页抓取)

    import urllib2 as url import cookielib,StringIO,gzip,json import pandas as pd import numpy as np #定义 ...

  8. R-CNN论文详解 - CSDN博客

    废话不多说,上车吧,少年 paper链接:Rich feature hierarchies for accurate object detection and semantic segmentatio ...

  9. Python开发【模块】:sqlalchemy

    一.对象映射关系(ORM) orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却 ...

  10. 使用Atom预览markdown

    1.打开任意.md文件(markdown源文件)2.windows : ctrl + shift + pmac : command + shift + p这条命令跟Sublime Text是一样的,打 ...