版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/richenyunqi/article/details/82184492
UVA - 1368. DNA Consensus String题解
欢迎访问我的Uva题解目录https://blog.csdn.net/richenyunqi/article/details/81149109
题目描述
题意解析
输入m个长度均为n的DNA序列,求一个DNA序列,到所有序列的总Hamming距离尽量小。两个等长字符串的Hamming距离等于字符不同的位置个数,例如,ACGT和GCGA的Hamming距离为2(左数第1, 4个字符不同)。输入整数m和n(4≤m≤50, 4≤n≤1000),以及m个长度为n的DNA序列(只包含字母A,C,G,T),输出到m个序列的Hamming距离和最小的DNA序列和对应的距离。如有多解,要求为字典序最小的解。
算法设计
为使Hamming距离和最小,可以找到输入字符串中相应位置下出现次数最多的字符作为所求DNA序列相应位置的字符,则该位置对应的距离即为m-该字符出现的次数。例如对以下4个DNA序列来说:
索引 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
序列1 | T | A | T | G |
序列2 | T | A | A | G |
序列3 | A | A | A | G |
序列4 | T | G | T | G |
应输出序列 | T | A | A | G |
Hamming距离 | 1 | 1 | 2 | 0 |
在索引0处,4个DNA序列中出现次数最多的字符是T,故应输出DNA序列在该位置的字符为T,该位置的Hamming距离为4(共有4个DNA序列)-3(T字符出现了3次)=1。其余位置也如此计算。注意当多个字符出现次数相同时需取字典序小的。
C++代码
#include<bits/stdc++.h>
#define _for(i,a,b) for(int i=(a);i<(b);++i)//for循环的一种简单写法的宏定义
using namespace std;
int main(){
int T,m,n;
scanf("%d",&T);
while(T--){
scanf("%d%d",&m,&n);
string input[m];
_for(i,0,m) cin>>input[i];//读入m个字符串
map<char,int>um;//存储m个字符串中相同位置出现的字符及其对应的次数,注意map按键有小到大的顺序存储
int error=0;//存储Hamming距离和
_for(i,0,n){
_for(j,0,m) ++um[input[j][i]];
char MAX='A';
for(auto&j:um)//查找出现次数最多的字符
if(j.second>um[MAX])
MAX=j.first;
putchar(MAX);//输出出现次数最多的字符
error+=m-um[MAX];//加上Hamming距离
um.clear();//清空map
}
printf("\n%d\n",error);//输出Hamming距离和
}
return 0;
}