【HIHOCODER 1052 】基因工程(贪心)

链接

问题描述

小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

题解

第二组方案为ATATATAT,同时我们经过这一组数据也可以看出解法。
AT=AC
AC=GT
GT=CT
即AT=AC=GT=CT那么可以将这一组选出第一个统一的字母(出现最多的为最佳),第二个。。。。
注意len%(len-k)!=0的情况

参考代码

import java.io.*;
import java.util.*;
public class Main {
	static final int N = (int) 1e5 + 10;
	static char a[] = new char[1005];
	static char f[] = new char[1005];
	static int vis[][] = new int[1005][1005];
    static int b[]= {0,'T'-'A','C'-'A','G'-'A'};
	public static void main(String[] args) {
		Scanner sc = new Scanner(new InputStreamReader(System.in));
		int T = sc.nextInt();
		while (T-- != 0) {
			String str = sc.next();
			int k = sc.nextInt();
			int len = str.length();
			a = str.toCharArray();
			int ans = 0;
			if(k>=len) {
				System.out.println(0);
				continue;
			}
			if (k <= len / 2)
				for (int i = 0, j = len - k; i < k; i++, j++) {
					if (a[i] != a[j])
						ans++;
				}
			else {
				for (int i = 0; i < len - k; i++) {
					for(int j=0;j<26;j++) vis[i][j]=0;
				}
				for (int i = 0; i < len; i += len - k) {
					for (int j = i; j < i + len - k; j++) {
						if(j>=len) break;
						vis[j-i][a[j]-'A']++;
					}
				}
				int mx,cnt;
				for(int i=0;i<len-k;i++) {
					mx=0;cnt=0;
					for(int j=0;j<4;j++) {
						if(vis[i][b[j]]>cnt) {
							mx=b[j];cnt=vis[i][b[j]];
						}
					}
					f[i]=(char)(mx+'A');
				}
				for (int i = 0; i < len; i += len - k) {
					for (int j = i; j < i + len - k; j++) {
						if(j>=len) break;
						if (a[j] != f[j - i]) {
							ans++;
						}
					}
				}
			}
			System.out.println(ans);
		}
		sc.close();
	}
}
posted @ 2017-07-26 19:38  江南何采莲  阅读(147)  评论(0编辑  收藏  举报