首页 > 试题广场 >

DNA序列

[编程题]DNA序列
  • 热度指数:133892 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

一个 DNA 序列由 A/C/G/T 四个字母的排列组合组成。 G 和 C 的比例(定义为 GC-Ratio )是序列中 G 和 C 两个字母的总的出现次数除以总的字母数目(也就是序列长度)。在基因工程中,这个比例非常重要。因为高的 GC-Ratio 可能是基因的起始点。

给定一个很长的 DNA 序列,以及限定的子串长度 N ,请帮助研究人员在给出的 DNA 序列中从左往右找出 GC-Ratio 最高且长度为 N 的第一个子串。
DNA序列为 ACGT 的子串有: ACG , CG , CGT 等等,但是没有 AGT , CT 等等

数据范围:字符串长度满足  ,输入的字符串只包含 A/C/G/T 字母

输入描述:

输入一个string型基因序列,和int型子串的长度



输出描述:

找出GC比例最高的子串,如果有多个则输出第一个的子串

示例1

输入

ACGT
2

输出

CG

说明

ACGT长度为2的子串有AC,CG,GT3个,其中AC和GT2个的GC-Ratio都为0.5,CG为1,故输出CG   
示例2

输入

AACTGTGCACGACCTGA
5

输出

GCACG

说明

虽然CGACC的GC-Ratio也是最高,但它是从左往右找到的GC-Ratio最高的第2个子串,所以只能输出GCACG。    
while True:
    try:
        str1=input()#记录字串
        n=int(input())#记录个数
        a=[]
        if len(str1) > n:#当n个数小于字符串长度时(可以移动框时)
            for i in range (len(str1)-n): #以步长为1移动框查找个数
                total=str1[i:i+n].count('G')+str1[i:i+n].count('C')
                a.append(total)#记录在list里
            index =a.index(max(a))#查找最大值index
            print(str1[index:(index+n)])#按长度打印
        elif len(str1) == n:#最后有个相等情况直接打印或者判断if ‘G’,‘C’ not in 返回空
            print(str1)
    except:
        break

发表于 2021-06-30 12:17:18 回复(0)
while True:
    try:
        s_list=input().split()
        s=''.join(s_list)
        n=int(input())
        sub_list=[]
        for i in range(len(s)-n+1):
            num=s[i:i+n].count('G')+s[i:i+n].count('C')
            sub_list.append(num)
        r=sub_list.index(max(sub_list))
        print(s[r:r+n])
    except:
        break
发表于 2021-05-08 08:57:21 回复(0)
while True:
    try:
        str = input()
        n = int(input())
        strings = []
        if n == len(str):
            print(str)
        else:
            for i in range(len(str) - n):
                    count = str[i:i+n].count('G') + str[i:i+n].count('C')
                    ratio = count / len(str[i:i+n])
                    if count > 0:
                        strings.append([str[i:i+n], ratio])
            ordered = sorted(strings, key= lambda x:x[1], reverse = True)
            print(ordered[0][0])
    except EOFError:
        break

发表于 2021-03-29 00:32:08 回复(0)
while True:
    try:
        str1=input()
        num=int(input())
        n=0
        str2=str1[:num]
        for i in range(len(str1)-num+1):
            m=str1.count('G',i,i+num)+str1.count('C',i,i+num)
            if m>n:
                n=m
                str2=str1[i:i+num]
        print(str2)
    except:
        break
发表于 2021-03-15 12:25:19 回复(0)

给定一个很长的DNA序列,以及要求的最小子序列长度,不知道为什么,最近总是把问题做复杂,是我理解差了还是题目描述不严密呢?但始终觉得这句话的意思是子串长度不固定,给定一个最小长度要求而已,而实际是按固定考虑。

附python借助队列存储移动窗口内符合条件的下标,时间复杂度0(n)

while True:
    try:
        s = input().strip()
        k = int(input())
        queue = []
        for i in range(k):
            if s[i] in 'CG':
                queue.append(i)
        max_ratio = len(queue)
        res = s[:k]
        for i in range(k, len(s)):
            if s[i] in 'CG':
                queue.append(i)
            if queue[0] <= i-k:
                queue.pop(0)
            if len(queue) > max_ratio:
                max_ratio = len(queue)
                res = s[i-k+1:i+1]
        print(res)
    except:
        break
编辑于 2021-02-20 22:17:53 回复(0)
滑动窗口解法
while True:
    try:
        s, k = input(), int(input())
        most, l, r = s[:k].count("C")+s[:k].count("G"), 0, k-1
        cal = most
        for i in range(1, len(s)-k+1):
            if s[k-1+i] in ("C", "G"):
                if s[i-1] not in ("C", "G"):
                    cal += 1
                    if cal > most:
                        most = cal
                        l, r = i, k-1+i
            else:
                if s[i-1] in ("C", "G"):
                    cal -= 1
        print(s[l:r+1])
    except:
        break


发表于 2020-12-17 21:59:16 回复(0)
while True:
    try:
        string, num = input().strip(), int(input().strip())
        C_and_G_counts = []
        for i in range(0, len(string)-num+1):
            sub_str = string[i:i+num]
            C_and_G_counts.append(sub_str.count('C') + sub_str.count('G'))
        index = C_and_G_counts.index(max(C_and_G_counts))
        print(string[index:index+num])
    except:
        break
        

编辑于 2020-12-09 15:55:41 回复(0)
# 2020年11月14日10:21:15
# 寻找第一个GC比例最高的子串
def high_gc_substr(seq, num):
    ratio = []
    for i in range(len(seq) - num + 1):
        sub_seq = seq[i:i+num]
#       计算G、C字母个数之和
        cnt = sub_seq.count("G") + sub_seq.count("C")
#       计算GC比例
        ratio.append(cnt / len(seq))
#   返回第一个最大值索引
    idx = ratio.index(max(ratio))
    return seq[idx:idx+num]

while True:
    try:
        seq = input()
        num = int(input())
        print(high_gc_substr(seq, num))
    except:
        break
        

发表于 2020-11-14 11:11:54 回复(0)
while True:
    try:
        a = input()
        b = int(input())
        char = a[:b]
        ra = char.count('C')+char.count('G')
        for i in range(1,len(a)-b+1):
            if a[i:i+b].count('C')+a[i:i+b].count('G') > ra:
                char = a[i:i+b]
                ra = char.count('C')+char.count('G')
        print(char)
    except:
        break

发表于 2020-11-06 12:11:59 回复(0)
while True:
    try:
        s, n = input(), int(input())
        res = s[0:n]
        ratio = (res.count('C') + res.count('G')) / n
        for i in range(1, len(s) - n):
            sub_s = s[i:i+n]
            tmp = (sub_s.count('C') + sub_s.count('G')) / n
            if tmp > ratio:
                ratio = tmp
                res = sub_s
        print(res)
    except:
        break
        

发表于 2020-09-29 17:57:19 回复(0)
笨方法,一个一个比较
while True:
    try:
        a, b = input(), int(input())
        maxStr, maxCnt = a[:b], a[:b].count("C") + a[:b].count("G")
        for i in range(0, len(a) - b):
            if a[i:i + b].count("C") + a[i:i + b].count("G") > maxCnt:
                maxCnt = a[i:i + b].count("C") + a[i:i + b].count("G")
                maxStr = a[i:i + b]
        print(maxStr)
    except:
        break
编辑于 2020-09-07 21:56:28 回复(0)
while True:
    try:
        str1 = input()
        n = int(input())
        maxGC = []
        for i in range(len(str1)-n+1):
            strList = []
            count = 0
            gcradio = 0
            for j in range(i,i+n):
                strList.append(str1[j])
                if str1[j] == 'G' or str1[j] == 'C':
                    count = count +1
            gcradio = count/n
            maxGC.append((str1[i:i+n], gcradio))
        # print(maxGC)
        maxratio = maxGC[0][1]
        maxDNA = maxGC[0][0]
        for one in maxGC:
            if one[1] > maxratio:
                maxratio = one[1]
                maxDNA = one[0]
        print(maxDNA)
    except:
        break
发表于 2020-08-30 20:54:05 回复(0)
因为用的是python,总的来说两种思路:
1、利用序列的count函数计算每个小片段G和C的个数,取最大即可;
2、每次直接使用python的函数总感觉在犯罪,下面分享一个正常思路的解法,有点动态规划的意思,利用一个滚动数组记录,滚动数组dp长度为题目要求小片段的长度l。
dp[0-l]代表小片段包含C和G的个数,当然了,每次dp[-1]代表长度为l的子串包含的G和C的总数。
假设原序列 AACTGTGCACGACCTGA, 小片段长度为5,初始化,dp为前五个字符的G和C的总数,即AACTG对应的dp为[0,0,1,1,2],当进行下一个片段(ACTGT)转移时,即索引从0-4的片段过渡到1-5的片段,这时候变化是:去掉了s[0]但是增加了s[5],又因为dp[4]存的是0-4片段G和C的总数,所以下一个dp[4]存的是1-4片段总数 + 第5个字符是否是G或C - 第0个字符是否是G或C,代码如下:


其中lcsdp是动态规划思想的函数,lcscount是使用了python的count函数的版本
def lcsdp(s, l):
    if len(s) <= l: return s
    slen = len(s)
    dp = [0]*l
    for i in range(l):
        dp[i] = dp[i-1] + (s[i] == 'G' or s[i] == 'C') # python支持负索引,dp[-1]有意义
    mxr, mxindex = dp[l-1], 0
    for i in range(l, slen):
        dp = dp[:l-1] + [dp[-1] + (s[i] == 'G' or s[i] == 'C') - (s[i-l] == 'G' or s[i-l] == 'C')]
        if dp[-1] > mxr:
            mxr = dp[-1]
            mxindex = i-l+1
    return s[mxindex:mxindex+l]
def lcscount(s, l):
    if len(s) <= l: return s
    slen = len(s)
    mxr, mxindex = 0, 0
    for i in range(slen-l+1):
        stmp = s[i:i+l]
        tmpr = stmp.count('G') + stmp.count('C')
        if tmpr > mxr:
            mxr = tmpr
            mxindex = i
    return s[mxindex:mxindex+l]
while True:
    try:
        s, l = input(), int(input())
        print(lcsdp(s, l))
    except:
        break


编辑于 2020-08-26 10:51:26 回复(0)
def counter(m):
    count=m.count('C')+m.count('G')
    return count
while True:
    try:
        count0=0
        nnstr=''
        str=input()
        n=int(input())
        for i in range(len(str)-5):
            nstr=str[i:i+n]
            count=counter(nstr)
            if count>count0:
                count0=count
                nnstr=nstr
        print(nnstr)
    except:
        break
发表于 2020-08-23 15:57:41 回复(0)
while True:
    try:
        s, n = input(), int(input())
        c = 0
        out = ''
        for i in range(len(s)+1-n):
            count = s[i:i+n].count('G') + s[i:i+n].count('C')
            if count > c:
                c = count
                out = s[i:i+n]
        print(out)
    except:
        break

发表于 2020-08-17 13:57:52 回复(0)
while True:
    try:
        a, b = input(), int(input())
        c = 0
        d = ''
        for i in range(len(a) - b + 1):
            res = a[i:i+b]
            n = res.count('G') + res.count('C')
            if n > c:
                c = n
                d = res
        print(d)
    except:
        break
发表于 2020-08-13 10:26:47 回复(0)

滑窗? 复杂度O(N)

while True:
    try:
        string = str(raw_input())
        N = int(input())
        dp = [0]*(len(string))
        maxval = 0
        for i in range(len(string)):
            if string[i] == "G" or string[i] == "C":
                maxval += 1
            dp[i]  = maxval
        maxval = dp[N-1] #注意此时maxval的初始化,因为下面的loop从1开始
        p = 0
        CGcount = 0
        for i in range(1,len(string)-N+1):
            CGcount = dp[i+N-1]-dp[i-1]
            if CGcount > maxval:
                maxval = CGcount
                p = i
        print(string[p:p+N])
    except:
        break
编辑于 2020-06-09 05:13:54 回复(0)
在pypy3.6.1版本测试通过,其他版本的字典默认无序,所以还是新版本好用
while True:
    try:
        s,N= input(),eval(input())
        ls,a = [],len(s)
        for k in range(1,a+1):
            for i in range(a-k+1):
                if len(s[i:i+k]) == N:
                    ls.append(s[i:i+k])
        dic = {}
        for j in ls:
            num = 0
            for m in j:
                if m == 'G'&nbs***bsp;m == 'C':
                    num += 1
            dic[j] = num
        lst = []
        lst = list(dic.items())
        lst.sort(key = lambda x:x[1],reverse = True)
        print(lst[0][0])
    except:
        break

发表于 2020-05-22 10:31:19 回复(0)
while 1:
    try:
        instr, strlen = input(), int(input())
        GCratio, flag, out = 0, 0, instr[0:strlen]
        for i in range(len(instr)-strlen):
            Substring = instr[i:i+strlen]
            if 'A' not in Substring and 'T' not in Substring:
                flag = 1
                print(Substring)
                break
            else:
                temp = Substring.count('G')+Substring.count('C')
                if temp>GCratio:
                    GCratio = temp
                    out = Substring
        if flag == 0:
            print(out)
    except:
        break

滑动窗口求解
发表于 2020-05-08 17:14:09 回复(0)