hihoCoder1052—基因工程

题目链接:传送门

时间限制: 1000ms
单点时限: 1000ms
内存限制: 256MB

描述

小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 
样例输出
1  
3   


解题思路:分成两种情况考虑

1.两个部分无相交,即只要考虑改变最少的字符使这两个部分相等

2.两个部分有相交,相交部分为bc,在bd中我们可以依次找出n个长度为Lab的部分k,即ad中这(n+1)个k都相等,假如有剩余k'部分,这个k'要和ac中的末端等长的部分相等,而此部分又是第(n+1)个k的起始一小节,即(n+1)个k的起始一小节和k'都要相等,这里可以这样处理一下,在字符串的末尾添加一些无用的字符p,使L(k'+p)=L(k),

即这(n+2)个部分都要相等,我们处理每个部分对应的某个字符(n个),假设字符相同的数目最多为m个,则最少需要修改的字符个数为n-m。


自己都不清楚自己写的是啥,哇的一声哭出来快哭了


#include <cstdio>  
#include <cstring>  
#include <cmath>  
#include <iostream>  
#include <queue>
#include <set>
#include <string>
#include <stack>
#include <algorithm>
#include <map>
#include <bitset>
using namespace std;  
typedef long long ll;
const int N = 1007;
const int M = 11;
const int INF = 0x3fffffff;
const int mod = 1e9+7;
const double Pi = acos(-1.0);
const double sm = 1e-9;

int main()
{
	int T;
	cin >> T;
	while( T-- ){
		string st; int k;
		map<char,int>mp;
		cin >> st >> k;
		int ans = 0,len = st.length();
		if( len == k ){ cout << 0 << endl; continue;}
		if( len >= 2*k ){
			for( int i = 0 ; i < k ; ++i ){
				if( st[i] != st[len-k+i]) ++ans;
			}
		}
		if( len < 2*k ){
			int t = len%(len-k);
			int n = len/(len-k);
			if( t != 0 ){
				int s = k-t;
				string st1(s,'*');
				st.append(st1);
				++n;
			}
			for( int i = 0 ; i < len-k ; ++i ){
				if( !mp.empty() ) mp.clear();
				int re = 0;
				for( int j = 0 ; j < n ; ++j ){
					if( st[i+j*(len-k)] == '*' ) continue;
					++re;
					++mp[st[i+j*(len-k)]];
				}
				int rec = 0;
				for( map<char,int>::iterator iter = mp.begin() ; iter != mp.end() ;
					++iter ){
						rec = max(rec,iter->second );
				}
				ans += re-rec;
			}
		}
		cout << ans << endl;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值