这个题我刚开始就想用容器来做,选了vector<map<char,int> >,相当于一个二维数组。每一个位置上的元素为一个map,map中就四种类型的元素,'A','T','C','G',对每一个位置对应的字母,这个map都+1,最后就成了统计每一个位置上四个字母的出现次数,找到出现次数最多的作为答案字符串上该位置的字符;如果出现次数一样多,就选字典序小的。
但是接下来思路乱了,我想的是排序找出第一个元素,但是后来发现为什么要排序,排map还是vector,我想不懂了,所以就没做下去。后来一想,向量每一个元素是一个map,那我只需要遍历每一个map,找到其中满足我们条件的就可以了。最后输出不同位置次数,只需要拿答案和原先的每一个字符串都比较一下,记一下数就行了。
但是,值得注意的是,我这两天被同一个错误卡了好几次,这就是变量作用域与是否需要初始化。我经常忘记每次把计数器、计数数组、标记数组初始化,或者初始化不当,导致最后答案错误。这种内部的逻辑错误很难发现,没办法,可能只能自己好好记住变量的含义,实在不行写几行汉语注释也可以啊。
#include <bits/stdc++.h>
using namespace std;
typedef map<char,int> mp;
typedef pair<char,int> pp;
vector<mp> v;
vector<string> st;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int m,n,w;
cin>>w;
while (w--) {
string s;
cin>>m>>n;
for (int i=0;i<n;i++) {
mp mm;
mm['A']=0;
mm['T']=0;
mm['C']=0;
mm['G']=0;
v.push_back(mm);
}
for (int i=0;i<m;i++) {
cin>>s;
st.push_back(s);
for (int j=0;j<n;j++) {
v[j][s[j]]++;
}
}
// for (int i=0;i<n;i++) {
// mp::iterator it2=v[i].begin();
// cout<<i<<endl;
// for (;it2!=v[i].end();it2++)
// cout<<(*it2).first<<' '<<(*it2).second<<' ';
// cout<<endl;
// }
string ans="";
//变量定义域没搞明白弄出的bug,两个这种bug
int mx=-1;
for (int i=0;i<n;i++) {
char c;
mp::iterator it1=v[i].begin();
for (;it1!=v[i].end();it1++) {
if ((*it1).second>mx) {
mx=(*it1).second;
c=(*it1).first;
}
else if ((*it1).second==mx)
c=min(c,(*it1).first);
}
ans+=c;
mx=-1;
}
int res=0;
for (int i=0;i<(int)st.size();i++) {
for (int j=0;j<(int)st[i].size();j++)
if (st[i][j]!=ans[j]) res++;
}
cout<<ans<<'\n'<<res<<endl;
v.clear();
st.clear();
}
return 0;
}