hiho_1052_基因工程

题目大意

    给出一个字符串(长度<=1000),字符串中的字符均为ATCG中的某一个。给出一个数字K,通过更改字符串中的某些字符,可以使得字符串的前K个字符形成的子串和最后K个字符形成的子串相同,求出最少更改的字符个数。

分析

    理解题意,画图之后,仿佛是KMP的结果,但是这和KMP没啥关系...画图分析之后,知道问题应该分情况讨论:记 len 为字符串的长度,result为最少更改的字符个数。 
(1) len >= 2*K 
    两个子串中间没有重合,直接进行比较相应位置上的字符,不同result就加1 
(2)len - K > K / 2 
    两个子串中间有重合,但是分析发现,需要加整个字符串分两个部分进行分别统计。t = 2*K-len. [t, K-t), [K-t, 2*(k-t)) 这两个区域应该相同; 且[0, t), [K-t, K), [len - t, len) 这三个区域相同。 
(3)len -K <= K / 2 
    画图可以知道,此时这个len长度的字符串被分成了连续的长度为(len - K)的一段段的子串,这些子串必须相同,最后一个子串可能长度没有(len - K),它就是前面那些子串的前缀。这样就需要判断,将len长度的字符串分割成连续的长度为(len - K)的子串,需要最少改动多少个字符使得这些子串相同。由于每个位置的字符只能为 ATCG中的一个,因此可以维护数组 gcount[len-K][4],其中 gcount[i][c] 表示 那些子串在各自的i位置上的字符为c(将A映射为0,T为1,C为2,G为3)的个数。遍历完一遍母串之后,求出gcount数组,对于每个位置i,都可以求出gcount[i]中的和 sum,以及最大值 max,sum-max即为需要发生的变动,将所有的位置处需要发生的变动加和。

实现

#pragma once
#pragma execution_character_set("utf-8")
// 本文件为utf-8 编码格式

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
char gene[1005];
int gcount[1005][4];
int main(){
	int T, k;
	scanf("%d", &T);	
	while (T--){
		getchar();
		scanf("%s", gene);
		scanf("%d", &k);
		int len = strlen(gene);
		int result = 0;
		if (len <= k){
			result = 0;
		}
		else if (len >= 2 * k){
			for (int i = 0; i < k; i++){
				if (gene[i] != gene[i + len - k])
					result++;
			}
		}
		else if(len - k > k / 2){
			int t = 2 * k - len;
			for (int i = t; i < k - t; i++){
				if (gene[i] != gene[i + k - t])
					result++;
			}
			for (int i = 0; i < t; i++){
				char a = gene[i];
				char b = gene[i + k - t];
				char c = gene[i + len - t];
				if (a == b){
					if (a != c)
						result++;
				}
				else if (a == c){
					if (a != b)
						result++;
				}
				else if (b == c){
					if (b != a)
						result++;
				}
				else
					result += 2;
			}
			
		}
		else{
			memset(gcount, 0, sizeof(gcount));
			for (int i = 0; i < len; i++){
				int index = i % (len - k);
				if (gene[i] == 'A')
					gcount[index][0]++;
				else if (gene[i] == 'T')
					gcount[index][1] ++;
				else if (gene[i] == 'C')
					gcount[index][2] ++;
				else if (gene[i] == 'G')
					gcount[index][3] ++;
			}
			for (int index = 0; index < (len - k); index++){
				int sum = 0, max = 0;
				for (int i = 0; i < 4; i++){
					sum += gcount[index][i];
					max = max > gcount[index][i] ? max : gcount[index][i];
				}
				result += (sum - max);
			}
		}
		printf("%d\n", result);
	}
	return 0;
}

 

posted @ 2016-05-20 21:04  农民伯伯-Coding  阅读(185)  评论(0编辑  收藏  举报