问题: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 techniques are simply to change some characters to eliminate all segments causing diseases. For example, we can repair a DNA "AAGCAG" to "AGGCAC" to eliminate the initial causing disease segments "AAG", "AGC" and "CAG" by changing two characters. Note that the repaired DNA can still contain only characters 'A', 'G', 'C' and 'T'.

You are to help the biologists to repair a DNA by changing least number of characters.
 
Input
The input consists of multiple test cases. Each test case starts with a line containing one integers N (1 ≤ N ≤ 50), which is the number of DNA segments causing inherited diseases.
The following N lines gives N non-empty strings of length not greater than 20 containing only characters in "AGCT", which are the DNA segments causing inherited disease.
The last line of the test case is a non-empty string of length not greater than 1000 containing only characters in "AGCT", which is the DNA to be repaired.

The last test case is followed by a line containing one zeros.
 
Output
For each test case, print a line containing the test case number( beginning with 1) followed by the
number of characters which need to be changed. If it's impossible to repair the given DNA, print -1.

Sample Input
2
AAA
AAG
AAAG    
2
A
TG
TGAATG
4
A
G
C
T
AGT
0

Sample Output
Case 1: 1
Case 2: 4
Case 3: -1

回答:题意给出一些不合法的模式DNA串,给出一个原串,问最少需要修改多少个字符,使得原串中不包含非法串
多串匹配,先想到AC自动机,需要求出最少需要修改多少字符,DP。
结合在一起
每一次沿着Trie树往下走,不能到达叶子结点罢了。不过对于为空但是合法的孩子需要进行处理。
DP方面,dp[i][j]表示前i个字符,当前为状态j的时候,需要修改的最少字符数。
从i-1的状态,找到之后的状态,如果字符与原串相同,则不变,否则+1。代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 100005
#define MOD 100000
#define inf 1<<29
#define LL long long
using namespace std;
struct Trie{
    Trie *next[4];
    Trie *fail;
    int kind,isword;
};
Trie *que[N],s[N];
int idx;
int id(char ch){
    if(ch=='A') return 0;
    else if(ch=='T') return 1;
    else if(ch=='C') return 2;
    return 3;
}
Trie *NewNode(){
    Trie *tmp=&s[idx];
    for(int i=0;i<4;i++) tmp->next[i]=NULL;
    tmp->isword=0;
    tmp->kind=idx++;
    tmp->fail=NULL;
    return tmp;
}
void Insert(Trie *root,char *s,int len){
    Trie *p=root;
    for(int i=0;i<len;i++){
        if(p->next[id(s[i])]==NULL)
            p->next[id(s[i])]=NewNode();
        p=p->next[id(s[i])];
    }
    p->isword=1;
}
void Bulid_Fail(Trie *root){
    int head=0,tail=0;
    que[tail++]=root;
    root->fail=NULL;
    while(head<tail){
        Trie *tmp=que[head++];
        for(int i=0;i<4;i++){
            if(tmp->next[i]){
                if(tmp==root) tmp->next[i]->fail=root;
                else{
                    Trie *p=tmp->fail;
                    while(p!=NULL){
                        if(p->next[i]){
                           tmp->next[i]->fail=p->next[i];
                           break;
                        }
                        p=p->fail;
                    }
                    if(p==NULL) tmp->next[i]->fail=root;
                }
                if(tmp->next[i]->fail->isword) tmp->next[i]->isword=1;
                que[tail++]=tmp->next[i];
            }
            else if(tmp==root) tmp->next[i]=root;
            else tmp->next[i]=tmp->fail->next[i];
        }
    }
}
int dp[1005][2005];
int slove(char *str,int len){
    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++){
            if(s[j].isword) continue;
            if(dp[i-1][j]==inf) continue;
            for(int k=0;k<4;k++){
                int r=s[j].next[k]->kind;
                if(s[r].isword) continue;
                dp[i][r]=min(dp[i][r],dp[i-1][j]+(id(str[i-1])!=k));
            }
        }
    }
    int ans=inf;
    for(int i=0;i<idx;i++) ans=min(ans,dp[len][i]);
    return ans==inf?-1:ans;
}
char str[1005];
int main(){
    int n,cas=0;
    while(scanf("%d",&n)!=EOF&&n){
        idx=0;
        Trie *root=NewNode();
        for(int i=0;i<n;i++){
            scanf("%s",str);
            Insert(root,str,strlen(str));
        }
        Bulid_Fail(root);
        scanf("%s",str);
        printf("Case %d: %d\n",++cas,slove(str,strlen(str)));
    }
    return 0;
}

DNA repair问题的更多相关文章

  1. hdu2457:DNA repair

    AC自动机+dp.问改变多少个字符能让目标串不含病毒串.即走过多少步不经过病毒串终点.又是同样的问题. #include<cstdio> #include<cstring> # ...

  2. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. 【POJ3691】 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Description B ...

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

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

    DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4815   Accepted: 2237 Descri ...

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

    题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...

  7. poj 3691 DNA repair(AC自己主动机+dp)

    DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5877   Accepted: 2760 Descri ...

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

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

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

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

随机推荐

  1. Unity3D实现赛车的灯光效果

    车灯的需求 在赛车游戏中,遇到灯光弱的环境,赛车车可以打开前车灯照亮路边及前方,那一定是非常酷! 也见过虚拟现实项目通过Unity模拟汽车车灯的效果,但是我还没有想到好的思路来实现. 我的思路 使用( ...

  2. oracle wm_concat(column)函数的使用

    oracle wm_concat(column)函数使我们经常会使用到的,下面就教您如何使用oraclewm_concat(column)函数实现字段合并,如果您对oracle wm_concat(c ...

  3. java 21 - 13 IO流之 合并流

    SequenceInputStream :表示其他输入流的逻辑串联. 构造方法摘要 SequenceInputStream(Enumeration<? extends InputStream&g ...

  4. 绕过D盾安全狗连接菜刀

    0x00 各种奇葩符号 现在基本上没啥用了,毕竟几年前的小玩意儿 /;.xxx.asp;.jpg /;.asp/.jpg 像这种各位看官可以忽略了,毕竟某狗和某盾也不是吃干饭的,写出来只是为了纪念一下 ...

  5. 23Mybatis_根据订单商品数据模型的练习对resultMap和resulttype的总结

    resultType: 作用: 将查询结果按照sql列名pojo属性名一致性映射到pojo中. 场合: 常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用re ...

  6. [IPSEC PKI]

    PKI: 对称加密 非对称加密(混合加密) 数字签名   理论概述: (1)预备知识 对称加密:加密密钥和揭秘蜜钥是同一个密钥 缺点:不适合在互联网上传输密钥 密钥维护工作量大 n(n-1)/2 : ...

  7. matlab如何读取未知行数,带头文件和字段名的txt文件

    文件格式是这样的 20120108 50024 X235RZB30801 01 15 2361 2362 2363 2364 2365 2366 2367 2368 2369 236A 236B 23 ...

  8. Nutch搜索引擎(第3期)_ Nutch简单应用

    1.Nutch命令详解 Nutch采用了一种命令的方式进行工作,其命令可以是对局域网方式的单一命令也可以是对整个Web进行爬取的分步命令. 要看Nutch的命令说明,可执行"Nutch&qu ...

  9. UITableView的性能优化10个小技巧

    通常你会发现一个图片类的app会在一个imageView上做下面这些事情: 1  下载图片(主要的内容图片+用户头像图片)2  更新时间戳3  展示评论4  计算动态的cell的高度 Tip#1 学习 ...

  10. pythonchallenge(一)

    PythonChallenge_1 一.实验说明 下述介绍为实验楼默认环境,如果您使用的是定制环境,请修改成您自己的环境介绍. 1. 环境登录 无需密码自动登录,系统用户名shiyanlou,密码sh ...