题目大意:
给出N个DNA序列,求取最短的序列的长度,满足所有给出的DNA序列是它的子序列。
输入:
第一行输入:测试样例组数 t;
然后是每一组样例的序列数N
然后输入N个DNA序列
算法分析:
要求的是最短序列的长度,那么我们可以通过枚举长度,然后判断是否能得到可行解的方式间接得到最优解,枚举长度后,我们可以设长度为已知的,找可行解的方式可以是搜索,那么我考虑如何搜索:
因为每个位置只可能有四种情况,所以我们可以枚举每种情况,然后记录每一个子序列当前未得到匹配的最前位置,递归地进行深度优先搜索,逐个的匹配,能匹配的话,指针后移指向当前序列的后一位置,不能匹配位置不变,因为序列中的元素不是串那种连续的形式,所以这种做法的正确性是有保证的,如果在给定长度下能够找到使所有的子序列完整匹配,那么存在可行解,择当前长度为最优解
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 11
using namespace std;
int t,k;
char s[MAX][MAX];
int id[MAX];
int len[MAX];
bool flag = false;
int h ( )
{
int ans = 0;
for ( int i = 0 ; i < k ; i++ )
ans = max ( ans , len[i]-id[i]);
return ans;
}
char ss[]="ACGT";
void dfs ( int length )
{
if ( !h() )
{
flag = true;
return;
}
if ( h() > length ) return;
bool yes = false;
int tid[MAX];
for ( int i = 0 ; i < k ; i++ )
tid[i] = id[i];
for ( int i = 0 ; i < 4 ; i++ )
{
for ( int j = 0 ; j < k ; j++ )
if ( s[j][id[j]] == ss[i] )
{
yes = true;
id[j]++;
}
if ( yes )
{
dfs ( length - 1 );
if ( flag ) return;
for ( int j = 0 ; j < k ; j++ )
id[j] = tid[j];
}
}
}
int main ( )
{
scanf ( "%d", &t );
while ( t-- )
{
scanf ( "%d" , &k );
int maxn = 0;
for ( int i = 0 ; i < k ; i++ )
{
scanf ( "%s" , s[i] );
len[i] = strlen ( s[i] );
maxn = max ( maxn ,len[i] );
id[i] = 0;
}
flag = false;
while ( 1 )
{
dfs ( maxn );
if ( flag )
{
printf ( "%d\n" , maxn );
break;
}
maxn++;
}
}
return 0;
}