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