zoukankan      html  css  js  c++  java
  • 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
    ", result);
    	}
    	return 0;
    }
    
  • 相关阅读:
    HDU 4947 GCD Array 容斥原理+树状数组
    Codeforces Round #363 (Div. 2)
    白书 博弈学习
    2016 Multi-University Training Contest 1
    KM算法 PK 最小费用最大流
    final 发布 领跑衫获奖感想
    2016"百度之星"
    爆打团队 2016.05.05 站立会议
    爆打团队 四则运算 beta视频
    爆打团队 2016.04.27 站立会议
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/5513433.html
Copyright © 2011-2022 走看看