poj 1699 搜索(AGCT组成最短串,题目有BUG)

题意:给定若干个DNA(由AGCT组成)串,求一个能够包含所有给定串的长串的最小长度。比如包含如下五个串:‘TCGG', 'GCAG', 'CCGC', 'GATC' 和 'ATCG的结果是CCGCAGATCGG。

思路:先用一个数组over[i][j]记录第i个串在第j个串前面时的最大重复字符数。然后搜索串的不同排列方式(相当与对不同串的前后进行全排列),求出不同方式的最短总串长度即可。

但是,怎么做都会WA,看了discuss知道错误出现在串有包含情况的数据中。但是题目并没有说不允许串的包含,不明所以。比如两个串“CC”和“ACCA”,按照题意应该“ACCA”就符合的嘛,但是这组数据偏偏要输出6,也就是求over[i][j]的时候,i不能包含j,也就是当第i个串的长度(leni)大于等于第j个串的长度(lenj)时,第i个串需要从第leni-lenj+1的位置开始匹配。这有点诡异吧!

#include <stdio.h>
#include <string.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define N 15
#define M 25
#define INF 0x3fffffff
char s[N][M];
int over[N][N],seq[N],visited[N];
int n,m,T,res,sumlen;
int test_overlap(int i,int j){
	char a[M],b[M];
	int lena,lenb,flag;
	strcpy(a,s[i]);
	strcpy(b,s[j]);
	lena = strlen(a);
	lenb = strlen(b);
	if(lena> lenb)//按照我之前的做法i直接赋值为0
		i = lena-lenb+1;
	else 
		i = 0;
	for(;i<lena;i++){
		for(j = flag = 0;j<lenb&&j+i<lena;j++)
			if(a[i+j] != b[j]){
				flag = 1;
				break;
			}
		if(!flag)
			return j;
	}
	return 0;
}
void dfs(int depth){
	int i,temp;
	if(depth == n){
		for(i = temp = 0;i<n-1;i++)
			temp += over[seq[i]][seq[i+1]];
		res = min(res,sumlen-temp);//一次排列的结果,所有字符的综合减去这种排列一共消掉的字符数
		return;
	}
	for(i = 0;i<n;i++)
		if(!visited[i]){
			seq[depth] = i;//seq保存全排列的数字
			visited[i] = 1;
			dfs(depth+1);
			visited[i] = 0;
		}
}
int main(){
	freopen("a.txt","r",stdin);
	scanf("%d",&T);
	while(T--){
		int i,j,k;
		res = INF;
		memset(visited,0,sizeof(visited));
		scanf("%d",&n);
		for(i = sumlen = 0;i<n;i++){
			scanf("%s",s[i]);
			sumlen += strlen(s[i]);
		}
		for(i = 0;i<n;i++)
			for(j = 0;j<n;j++)
				if(i != j)
					over[i][j] = test_overlap(i,j);
		dfs(0);
		printf("%d\n",res);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值