问题: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. bundle是什么?

    bundle就是一个数据对象,像Map,HashMap一样key-value键值对的方式存放数据.在android中用于应用程序之间数据传输,不过是要靠对象使用的 谢谢,又知道了一种在Activity ...

  2. TestLink学习五:TestLink1.9.13和JIRA6.3.6的集成

    testlink和jira的集成,一般步骤: 第1步:System-Issue Tracker Management添加JIRA的db模式.第2步:测试项目管理,“Issue Tracker Inte ...

  3. js的nextSibling,属性兼容IE和FF等浏览器

    Firefox中 空白字符,比如回车,空格等也算作一个Node 就是firstChild,nextsbiling这两个.下面给出函数吧.还是代码比较说明问题代码都是网上来的.不过要注意的是,getNe ...

  4. Java中的Random()函数

    今天在做Java练习的时候注意到了Java里面的一个随机函数——Random,刚开始只是知道这个函数具有随机取值的作用,于是上网搜索了资料一番,做了一下一些关于Random函数的总结:   Java中 ...

  5. 元祖签约K2 BPM,引领绿色健康食品!

    漫步街头,我们经常会被一些鲜艳的红色招牌所吸引,走进去会发现这里有一些普通西饼店不会卖的东西,比如红蛋.年糕.粽子.喜饼.等上海传统食品等......这就是元祖食品. 随着人们生活品质的不断提升,元祖 ...

  6. Linux Shell编程二

    以"``"符号包含的内容不是字符串,而是代表这是一个shell命令. echo "today is" `date` 前面是字符,后面`date`表示执行date ...

  7. EL表达式 (详解)

    L表达式      1.EL简介 1)语法结构        ${expression} 2)[]与.运算符      EL 提供.和[]两种运算符来存取数据.      当要存取的属性名称中包含一些 ...

  8. 使用OneNote的COM组件,实现OCR功能。

    背景 在业务系统开发的过程中,很多情况下会去识别图片中的相关信息,并且把信息录入到系统中.现在希望通过自动化的方式录入,就有了以下的工作.在对比了几个OCR软件在中文识别方面的准确率后,决定使用微软的 ...

  9. jquery-ajax-async之浏览器差异

    最近的PC项目遇到了一个问题,日志记录程序会在1s内多次发起对首页的请求,一时间没有找到原因. 简单描述一下问题:访问一个首页的时候,由于代码质量不高的原因,访问就连接数据库,但是同时存在的问题是一秒 ...

  10. mysql使用基础 sql语句(一)

    csdn博文地址:mysql使用基础 sql语句(一)  点击进入 命令行输入mysql -u root -p,回车再输入密码,进入mysql. 终端命令以分号作为一条语句的结束,可分为多行输入,只需 ...