DNA Laboratory
Time Limit: 5000MS   Memory Limit: 30000K
Total Submissions: 2892   Accepted: 516

Description

Background 
Having started to build his own DNA lab just recently, the evil doctor Frankenstein is not quite up to date yet. He wants to extract his DNA, enhance it somewhat and clone himself. He has already figured out how to extract DNA from some of his blood cells, but unfortunately reading off the DNA sequence means breaking the DNA into a number of short pieces and analyzing those first. Frankenstein has not quite understood how to put the pieces together to recover the original sequence. 
His pragmatic approach to the problem is to sneak into university and to kidnap a number of smart looking students. Not surprisingly, you are one of them, so you would better come up with a solution pretty fast. 
Problem 
You are given a list of strings over the alphabet A (for adenine), C (cytosine), G (guanine), and T (thymine),and your task is to find the shortest string (which is typically not listed) that contains all given strings as substrings. 
If there are several such strings of shortest length, find the smallest in alphabetical/lexicographical order.

Input

The first line contains the number of scenarios. 
For each scenario, the first line contains the number n of strings with 1 <= n <= 15. Then these strings with 1 <= length <= 100 follow, one on each line, and they consist of the letters "A", "C", "G", and "T" only.

Output

The output for every scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. Then print a single line containing the shortest (and smallest) string as described above. Terminate the output for the scenario with a blank line.

Sample Input

1
2
TGCACA
CAT

Sample Output

Scenario #1:
TGCACAT

Source

TUD Programming Contest 2004, Darmstadt, Germany
 
题意:给定n个由A,G,C,T构成的字符,现在要找到一个字符串使得该字符串能匹配到给定的n个字符,并且使得这个字符串字典序最小。
思路:首先n个字符中可能有一些字符包含于另一些字符当中,那么这些被包含的字符当然不需要考虑了。先预处理出一个字符的头部加上另一个字符后整体增加的长度大小,存于dist[i][j](在字符j的头部添加上字符i后整体增加的长度)中。显然可以用状压dp解决,dp[state][i]:由state状态中的字符构成的最小字符串,且这个字符串是以第i个字符开头的,dp[state][i]记录这个字符串的长度。
状态转移:dp[state|1<<j][j]=min(dp[state|1<<j][j],dp[state][i]+dist[j][i]);
利用dp,先得到字符串最小长度是多少,并且也知道这个字符串的头部应该是由哪个字符构成的。再从头部至尾部递归的寻找最小的字符串的组成。
AC代码:
#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<bitset>
#include<set>
#include<map>
#include<cmath>
using namespace std;
#define N_MAX 16
#define MOD 100000000
#define INF 0x3f3f3f3f
typedef long long ll;
string s[N_MAX];
int dp[<<N_MAX][N_MAX];//状态是i,当前字符串的头部是字符串j时总字符串最小长度
int dist[N_MAX][N_MAX];//dist[i][j]:在j的前面加上字符串i,整体字符串所需要增加的长度
vector<string>vec;
int t,n; void init() {
memset(dp, INF, sizeof(dp));
memset(dist, , sizeof(dist));
for (int i = ; i < n; i++) {
for (int j = ; j < n;j++) {
if (i == j)continue;
int sz = min(vec[i].size(), vec[j].size());
for (int k = sz; k >= ;k--) {
if (vec[i].substr(vec[i].size() - k) == vec[j].substr(, k)) {//首尾重复的部分不算
dist[i][j] = vec[i].size() - k;
break;
}
}
}
}
}
string res = "";
void dfs(int head,int state) {//state状态表示当前还有哪些字符串没有被使用
if (state == )return;
string min_s = "Z";int min_head;
for (int i = ; i < n;i++) {
if ((state >> i & )&&dp[state|<<head][head]==dp[state][i]+dist[head][i]) {
int Len = vec[head].size() - dist[head][i];
string s = vec[i].substr(Len);
if (min_s > s) { min_s = s; min_head = i; }
}
}
res += min_s;
dfs(min_head, state ^ ( << min_head));
} int main() {
int t; scanf("%d",&t);
for (int cs = ; cs <= t;cs++) {
scanf("%d",&n);
printf("Scenario #%d:\n",cs);
for (int i = ; i < n; i++) cin >> s[i];
vec.clear();
for (int i=; i < n;i++) {//检查是否有重复的字符串
bool flag = ;
for (int j = ; j < n;j++) {
if (i == j || s[i].size() > s[j].size())continue;
if (s[j].find(s[i]) != string::npos) {//找到重复
flag = ; break;
}
}
if (flag)vec.push_back(s[i]);
}
if (vec.size() == ) { cout << s[] << endl << endl; continue; }
sort(vec.begin(), vec.end());
n = vec.size();
init();
int allstates = << n;
for (int i = ; i < n;i++) {
dp[ << i][i] = vec[i].size();
} for (int state = ; state < allstates; state++) {
for (int i = ; i < n;i++) {
if (dp[state][i] == INF)continue;
for (int j = ; j < n; j++) {
if (!(state >> j & )) {
dp[state | << j][j] = min(dp[state | << j][j], dp[state][i] + dist[j][i]);
}
}
}
}
int head=;
for(int i=;i<n;i++)
if (dp[allstates - ][i] < dp[allstates-][head]) {
head = i;
}
res = vec[head];
dfs(head, (allstates -)^ ( << head));//!!!!
cout << res << endl<<endl;
}
return ;
}
 

poj 1795 DNA Laboratory的更多相关文章

  1. POJ 1795 DNA Laboratory(状压DP)

    [题目链接] http://poj.org/problem?id=1795 [题目大意] 给出n个字符串,求一个最小长度的串,该串包含给出的所有字符串. 要求长度最小且字典序最小. [题解] dp[i ...

  2. POJ 1795 DNA Laboratory (贪心+状压DP)

    题意:给定 n 个 字符串,让你构造出一个最短,字典序最小的字符串,包括这 n 个字符串. 析:首先使用状压DP,是很容易看出来的,dp[s][i] 表示已经满足 s 集合的字符串以 第 i 个字符串 ...

  3. POJ 1795

    DNA Laboratory Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 1425   Accepted: 280 Des ...

  4. poj 1007 DNA Sorting 解题报告

    题目链接:http://poj.org/problem?id=1007 本题属于字符串排序问题.思路很简单,把每行的字符串和该行字符串统计出的字母逆序的总和看成一个结构体.最后把全部行按照这个总和从小 ...

  5. POJ 2778 DNA Sequence(AC自动机+矩阵加速)

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9899   Accepted: 3717 Desc ...

  6. poj 2778 DNA Sequence ac自动机+矩阵快速幂

    链接:http://poj.org/problem?id=2778 题意:给定不超过10串,每串长度不超过10的灾难基因:问在之后给定的长度不超过2e9的基因长度中不包含灾难基因的基因有多少中? DN ...

  7. POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)

    题目链接:http://poj.org/problem?id=2778 题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) ...

  8. POJ 3691 DNA Sequence (AC自动机 + 矩阵 有bug,待修改)

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9889   Accepted: 3712 Desc ...

  9. [POJ 1007] DNA Sorting C++解题

        DNA Sorting Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 77786   Accepted: 31201 ...

随机推荐

  1. 十四、MySQL UPDATE 查询

    MySQL UPDATE 查询 如果我们需要修改或更新 MySQL 中的数据,我们可以使用 SQL UPDATE 命令来操作.. 语法 以下是 UPDATE 命令修改 MySQL 数据表数据的通用 S ...

  2. spark实战之网站日志分析

    前面一篇应该算是比较详细的介绍了spark的基础知识,在了解了一些spark的知识之后相必大家对spark应该不算陌生了吧!如果你之前写过MapReduce,现在对spark也很熟悉的话我想你再也不想 ...

  3. 南阳 ACM16 矩形嵌套 动态规划

    矩形嵌套 时间限制:3000 ms  |           内存限制:65535 KB 难度:4   描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c, ...

  4. POJ 2586 贪心+枚举

    Y2K Accounting Bug Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15626   Accepted: 78 ...

  5. Leetcode 105. 从前序与中序遍历序列构造二叉树

    题目链接 题目描述 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder ...

  6. LINUX下实现按秒执行计划任务

    由于linux最小单位为分,但是很多需求上需要按秒执行,如30秒请求一个URL地址之类的,思路很简单就是修改计划任务脚本用循环控制,代码如下: #!/bin/bash PATH=/bin:/sbin: ...

  7. Leetcode 643.子数组最大平均数I

    子数组最大平均数I 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数. 示例 1: 输入: [1,12,-5,-6,50,3], k = 4 输出: 12.75 解释: ...

  8. [oldboy-django][2深入django]ORM操作

    推荐学习博客:http://www.cnblogs.com/wupeiqi/articles/6216618.html 需求: 汇总django orm操作,代替原生mysql语句来操作数据库:里面内 ...

  9. [python][django学习篇][14]markdown 代码高亮

    1 修改detail视图函数,渲染文件的时候,增加codehight拓展 post.body = markdown.markdown(post.body, extensions=[ 'markdown ...

  10. 爬虫:Scrapy4 - Spiders

    Spider 类定义了如何爬取某个(或某些)网站.包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item).Spider就是定义爬取的动作以及分析某个网页(或者有些网 ...