描述<原题链接
小Hi和小Ho正在进行一项基因工程实验。他们要修改一段长度为N的DNA序列,使得这段DNA上最前面的K个碱基组成的序列与最后面的K个碱基组成的序列完全一致。
例如对于序列"ATCGATAC"和K=2,可以通过将第二个碱基修改为"C"使得最前面2个碱基与最后面两个碱基都为"AC"。当然还存在其他修改方法,例如将最后一个碱基改为"T",或者直接将最前面两个和最后面两个碱基都修改为"GG"。
小Hi和小Ho希望知道在所有方法中,修改碱基最少的方法需要修改多少个碱基。
输入
第一行包含一个整数T(1 <= T <= 10),代表测试数据的数量。
每组测试数据包含2行,第一行是一个由"ATCG"4个大写字母组成的长度为N(1 <= N <= 1000)的字符串。第二行是一个整数K(1 <= K <= N)。
输出
对于每组数据输出最少需要修改的碱基数量。
2 ATCGATAC 2 ATACGTCT 6
本题双线性扫描处理匹配问题。关键点在于处理前后两个串交集部分的匹配。以as和bs表示两个串。
可以看出
#include <string.h> #include <vector> #include <algorithm> #include <iostream> using namespace std; int calc(string as,string bs,int k){ //bs[0~k]==as[n-k~n] int n=as.length(); if(k==n) return 0; int num=0; for(int i=0;i<n;i++){ if(i<k){ if(i>=n-k) break;///very important.... int j=i; vector<char> ss; ss.push_back(as[i]); while(true){ ss.push_back(bs[j]); if(j>=k) break; j+=(n-k); } // for test for(int s=0;s<ss.size();s++){ cout<<ss[s]<<" "; }cout<<endl; sort(ss.begin(),ss.end()); char lst=0;int cnt=0;int mcnt=0; for(int s=0;s<ss.size();s++){ if(lst!=ss[s]) cnt=1,lst=ss[s]; else cnt++; mcnt=max(mcnt,cnt); } mcnt=max(mcnt,cnt); num+=(ss.size()-mcnt); } else if(i<n-k){ if(as[i]!=bs[i]) num++; } else break; } return num; } int main(){ int cases;cin>>cases; for(int i=0;i<cases;i++){ char buf[1002]; cin>>buf; string temp=buf; int n;cin>>n;int len=strlen(buf); string as=temp.substr(0,n),bs=temp.substr(len-n,n); int k=(n-1)-(len-n)+1; //cout<<as<<endl<<bs<<endl<<"k:"<<k<<endl; if(k<0) k=0; cout<<calc(as,bs,k)<<endl; } return 0; }
据说上面不能ac,没查哪里写错了。发一个自己ac的版本。
#include <string.h> #include <vector> #include <algorithm> #include <iostream> using namespace std; int calc(string as,string bs,int k){ //bs[0~k]==as[n-k~n] int n=as.length(); if(k==n) return 0; int num=0; for(int i=0;i<n;i++){ if(i<k){ if(i>=n-k) break; int j=i; vector<char> ss; ss.push_back(as[i]); while(true){ ss.push_back(bs[j]); if(j>=k) break; j+=(n-k); } sort(ss.begin(),ss.end()); char lst=0;int cnt=0;int mcnt=0; for(int s=0;s<ss.size();s++){ if(lst!=ss[s]) cnt=1,lst=ss[s]; else cnt++; mcnt=max(mcnt,cnt); } mcnt=max(mcnt,cnt); num+=(ss.size()-mcnt); } else if(i<n-k){ if(as[i]!=bs[i]) num++; } else break; } return num; } int main(){ int cases;cin>>cases; for(int i=0;i<cases;i++){ char buf[1002]; cin>>buf; string temp=buf; int n;cin>>n;int len=strlen(buf); string as=temp.substr(0,n),bs=temp.substr(len-n,n); int k=(n-1)-(len-n)+1; if(k<0) k=0; cout<<calc(as,bs,k)<<endl; } return 0; }