问题: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. 2014 Super Training #9 F A Simple Tree Problem --DFS+线段树

    原题: ZOJ 3686 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686 这题本来是一个比较水的线段树,结果一个ma ...

  2. 2016百度之星-初赛(Astar Round2A)AII X

    Problem Description F(x,m) 代表一个全是由数字x组成的m位数字.请计算,以下式子是否成立: F(x,m) mod k ≡ c Input 第一行一个整数T,表示T组数据. 每 ...

  3. 导航 tab

  4. Java反射机制的学习

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

  5. 【转】【SSE】基于SSE指令集的程序设计简介

    基于SSE指令集的程序设计简介 作者:Alex Farber 出处:http://www.codeproject.com/cpp/sseintro.asp SSE技术简介 Intel公司的单指令多数据 ...

  6. 静态时序分析(static timing analysis) --- 时序路径

    时序分析工具会找到且分析设计中的所有路径.每一个路径有一个起点(startpoint)和一个终点(endpoint).起点是设计中数据被时钟沿载入的那个时间点,而终点则是数据通过了组合逻辑被另一个时间 ...

  7. SQL SERVER with递归示例一则

    WITH SUBQUERY AS ( SELECT ORGID FROM OM_ORGANIZATION WHERE PARENTORGID = 'ROOT' UNION ALL SELECT B.O ...

  8. Web 服务编程,REST 与 SOAP(转)

    原文地址:Web 服务编程,REST 与 SOAP REST 简介 在开始我们的正式讨论之前,让我们简单看一下 REST 的定义. REST(Representational State Transf ...

  9. [iOS翻译]Cocoa编码规范

        简介: 本文整理自Apple文档<Coding Guidelines for Cocoa>.这份文档原意是给Cocoa框架.插件及公共API开发者提供一些编码指导,实质上相当于Ap ...

  10. The specified LINQ expression contains references to queries that are associated with different contexts

    今天在改写架构的时候,遇到这么个错误.当时单从字面意思,看上去错误是由join的两个不同的表来源不一致引起的. 其中的videoResult和deerpenList均来自与同一个edmx文件,所以两个 ...