HDU 1560 DNA sequence
HDU 1560 DNA sequence
21世纪可是生物科技大放异彩的时代!我们都知道基因是由DNA构成的,而DNA则由四种核苷酸碱基组成:A(腺嘌呤)、C(胞嘧啶)、G(鸟嘌呤)和T(胸腺嘧啶)。在现代计算分子生物学中,寻找DNA/蛋白质序列的最长公共子序列是个经典问题。不过今天这道题有点特别——给定若干DNA序列,你需要构造出一个最短的新序列,使得每个给定序列都是它的子序列。
举个栗子🌰,给定"ACGT"、"ATGC"、"CGTT"和"CAGT",你可以这样构造新序列(虽然不一定唯一,但保证是最短的):
输入
第一行是测试用例数量t。接着t个测试用例,每个用例第一行是整数 \(n\) \((1≤n≤8)\)表示DNA序列数量,随后n行每行一个DNA序列(保证每个序列长度在1到5之间)。
输出
对每个测试用例,输出一行表示能构造出的最短序列长度。
样例
| \(Input\) | \(Output\) |
|---|---|
| 1 4 ACGT ATGC CGTT CAGT |
8 |
题解
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N = 10;
int T,n,deep;
string DNA[N],ans = " ",spi[4] = {"A","G","C","T"};
int fin[N],tmp[N],siz[N],cnt[N],index[N*3];
int h(){
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=n;i++){
for(int j=fin[i]+1;j<=siz[i];j++) cnt[index[DNA[i][j]-'A']]++;
for(int j=0;j<4;j++) tmp[j] = max(tmp[j],cnt[j]),cnt[j] = 0;
}
int res = 0;
for(int i=0;i<4;i++) res += tmp[i];
return res;
}
bool IDAStar(int step){
int est = h();
if(!est) return true;
if(step+est>deep) return false;
int rec[N];
for(int i=0;i<4;i++){
memcpy(rec,fin,sizeof(fin));
bool flag = 0;
for(int j=1;j<=n;j++){
if(DNA[j][fin[j]+1]==spi[i][0]){
fin[j]++;
flag = 1;
}
}
if(flag && IDAStar(step+1)) return true;
memcpy(fin,rec,sizeof(rec));
}
return false;
}
void init(){
memset(fin,0,sizeof(fin));
deep = 0;
}
signed main(){
cin>>T;
for(int i=0;i<4;i++) index[spi[i][0]-'A'] = i;
while(T--){
init();
cin>>n;
for(int i=1;i<=n;i++){
cin>>DNA[i];
siz[i] = DNA[i].size();
DNA[i] = " " + DNA[i];
deep = max(deep,siz[i]);
}
while(!IDAStar(0)) deep++;
cout<<deep<<'\n';
}
return 0;
}
使用下一位未匹配进行估价。
注意到这里对比前后状态的方法很有趣,新建数组然后复制下来。
\(END\)

浙公网安备 33010602011771号