最长公共子序列问题(Longest-Common-Subsequence,LCS)

S1=ACCGGTCGAGTGCGCGGAAGCCGGCCGAA
S2=GTCGTTCGGAATGCCGTTGCTCTGTAAA
如上面的两个DNA串中,最长的公共存在是
S3=GTCGTCGGAAGCCGGCCGAA。

在这里插入图片描述

含义:
1)若i=0或j=0,即其中一个序列的长度为零,则二者的LCS的长度为0,LCS=Φ;
2)若xi=yj,则Xi和Yj的LCS是在Xi-1和Yj-1的LCS之后附加将xi (也即yj)得到的,所以

c[i,j]=c[i-1,j-1]+1;

3)若xi≠yj,则Xi和Yj的LCS的最后一个字符不会是xi或yj(不可能同时等于两者,或与两者都不同),此时该LCS应等于Xi-1和Yj的LCS与Xi和Yj-1的LCS之中的长者。所以

c[i,j]=max(c[i-1,j],c[i,j-1]);

使用递推解法在字符串稍微长一些,速度就会很明显地慢起来了
这里使用记忆化搜索的动态规划解法

data={(-1,-1):''}
def LCS(i,j):
    global x,y,data
    if i==-1 or j==-1:
        data[(i,j)]=''
        return data[(i,j)]
    if (i,j) in data:
        return data[(i,j)]
    if  i>=0 and j>=0 and x[i]==y[j]:
        data[(i,j)]=LCS(i-1,j-1)+x[i]
        return data[(i,j)]
    elif i>=0 and j>=0 and x[i]!=y[j]:
        s1=LCS(i,j-1)
        s2=LCS(i-1,j)
        if len(s1)>len(s2):
            data[(i,j)]=s1
            return s1
        else:
            data[(i,j)]=s2
            return s2

测试代码如下

"""
x=input("输入序列x:\n")
y=input("输入序列y:\n")
"""
x="ACCGGTCGAGTGCGCGGAAGCCGGCCGAA"
y="GTCGTTCGGAATGCCGTTGCTCTGTAAA"


data={(-1,-1):''}
def LCS(i,j):
    global x,y,data
    if i==-1 or j==-1:
        data[(i,j)]=''
        return data[(i,j)]
    if (i,j) in data:
        return data[(i,j)]
    if  i>=0 and j>=0 and x[i]==y[j]:
        data[(i,j)]=LCS(i-1,j-1)+x[i]
        return data[(i,j)]
    elif i>=0 and j>=0 and x[i]!=y[j]:
        s1=LCS(i,j-1)
        s2=LCS(i-1,j)
        if len(s1)>len(s2):
            data[(i,j)]=s1
            return s1
        else:
            data[(i,j)]=s2
            return s2

s=LCS(len(x)-1,len(y)-1)
print(s)

测试结果如下

GTCGTCGGAAGCCGGCCGAA

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值