UVa 1368 DNA Consensus String (DNA序列)

题意:

给一些DNA序列(字符串只包含ACGT四种字母),求一个与这些DNA序列Hamming距离和最小的字符串,如果有多个这种字符串则输出字典序最小的那个,并求出最小Hamming距离和。

两个等长字符串的Hamming距离等于字符不同的位置的个数。

例如:ACGT和GCAT的Hamming距离是2.(左数第1,4个字符不同)

思路:

具体到每个位置考虑。最终的字符串在每个位置上的字母一定都是和输入DNA序列相应位置重合次数最多的那个。

因此只需统计输入所有DNA序列在每个位置重复出现字母次数。

用a[0][i], a[1][i], a[2][i], a[3][i]分别表示A,C,G,T在第i个位置(起始位置是0)出现的次数和

在该位置上的Hamming距离和是:

m-Max[i];Max[i]是输入DNA序列在位置i最大重合次数,即

Max[i] = max(a[0][i], a[1][i], a[2][i], a[3][i]);

但是同时又需要考虑这个最大重合次数的字母是什么,所以可以在max函数添加一个变量,用以标记最大的字母下标index,此下标与a[0][i], a[1][i], a[2][i], a[3][i]中的0,1,2,3相照应,因此初始化一个字符数组即可。

s1[4] = { 'A','C','G','T' };

#include <stdio.h>
#include <string.h>
#define maxn 1010
int max(int a, int b, int c, int d, int *inde)
{
	int max1;
	max1 = a > b ? a : b;
	max1 = max1 >= c ? max1 : c;
	max1 = max1 >= d ? max1 : d;
	if (max1 == a) *inde = 0;
	else if (max1 == b) *inde = 1;
	else if (max1 == c) *inde = 2;
	else *inde = 3;
	return max1;
}
int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	int T, m, n, i, j;
	char s[50][maxn], s1[4] = { 'A','C','G','T' };
	int a[4][maxn],index[maxn],Max[maxn];
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d%d", &m, &n);
		for (i = 0;i < m;i++)
			scanf("%s", s[i]);
		memset(a, 0, sizeof(a));
		for (i = 0;i < n;i++)
		{
			for (j = 0;j < m;j++)
			{
				if (s[j][i] == 'A') a[0][i]++;
				else if (s[j][i] == 'C') a[1][i]++;
				else if (s[j][i] == 'G') a[2][i]++;
				else a[3][i]++;
			}
			Max[i] = max(a[0][i], a[1][i], a[2][i], a[3][i], &index[i]);
		}
		int dis = 0;
		for (i = 0;i < n;i++)
		{
			putchar(s1[index[i]]);
			dis += m - Max[i];
		}
		printf("\n%d\n", dis);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值