HihoCoder 基因工程

原题链接 http://hihocoder.com/problemset/problem/1052

问题:给定由ATCG组成的长度为N的字符串S,求解最少的改动次数,使得前K个字符序列与后K个字符序列相同,其中 1  <= K <= N

分析:

1)对于长度相同的两个字符串 A 和 B 来说,要将两个字符串变为相同,只需改动所有 Ai 与 Bi 不相同的位置,将 Ai 改成 Bi 或者 Bi 改成 Ai 即可;

2)当 K <= N / 2 时,前K个字符序列 与 后K个字符序列 没有交集,如下图所示,因此按照1)处理即可;

3)当 K > N / 2 时,前K个字符序列 与 后K个字符序列 存在交集,如下图所示,Sn-k...Sk-1 既属于 前K个字符序列 又属于 后K个字符序列:

为了方便描述,取 m = n - k,为满足 前K个字符序列 与 后K个字符序列 相同,S中的元素必须满足如下图所示的相等关系:

这些相等关系约束,相当于将S划分为以下几个字符集合:U0 = {S0, Sm, ..., Sj*m},U1 = {S1, Sm+1, ..., Sj*m+1},...,Ui = {Si, Sm+i ... Sj*m+i},其中 i < m 且 Sj*m+i < N。

针对每一个集合Ui,只需保持出现次数最多的字符不变,将其他字符替换成该字符即可。此时,需修改次数 = 字符总数 - 出现最多的字符数。

显然,2)同样可以采用3)这样的方式处理,只是此时每个集合Ui只包含两个元素。

规则如下:

1)依次遍历每个集合 U0 = {S0, Sm, ..., Sj*m},U1 = {S1, Sm+1, ..., Sj*m+1},...,Ui = {Si, Sm+i ... Sj*m+i},其中 i < min(m, k) 且 Sj*m+i < N

2)针对每个集合Ui,需修改次数 = 字符总数 - 出现最多的字符数

3)累加每个集合Ui的需修改次数即可

代码如下:

 1 def solve():
 2     T = int(input())
 3     for i in range(T):
 4         S = raw_input()
 5         K = int(raw_input())
 6         ret = do_solve(S.strip(" "), K)
 7         print(str(ret))
 8 
 9 
10 def do_solve(S, K):
11     ret = 0
12     step = len(S) - K
13     cnt = [0, 0, 0, 0]
14     for i in range(min(K, step)):
15         cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0
16         j = i
17         while j < len(S):
18             if S[j] == 'A':
19                 cnt[0] = cnt[0] + 1
20             elif S[j] == 'T':
21                 cnt[1] = cnt[1] + 1
22             elif S[j] == 'C':
23                 cnt[2] = cnt[2] + 1
24             elif S[j] == 'G':
25                 cnt[3] = cnt[3] + 1
26             j += step
27         ret += sum(cnt) - max(cnt)
28     return ret
29 
30 
31 solve()
原文地址:https://www.cnblogs.com/moderate-fish/p/12446073.html