序列a和b的最长公共子序列(LCS)的长度可以在O(len(a)len(b))
时间内由
if a[i] != b[j]
c[i, j] = max(c[i - 1][j], c[i][j - 1])
else
c[i][j] = max(c[i - 1][j], c[i][j - 1], 1 + c[i - 1][j - 1])
其中c[i][j]
是a[0:i]
和b[0:j]
的LCS的长度。您能以多快的速度计算x
和y
之间的所有序列对的LCS,其中x
和y
是序列列表?
我尝试直接计算每一对,这需要
时间,它是x
和y
的总序列长度的乘积。
答案 0 :(得分:0)
首先,
您的重复关系是 错误
LCS(假设您自下而上)
if a[i] != b[j]
c[i, j] = max(c[i - 1][j], c[i][j - 1]) # fine
else
c[i][j] = 1 + c[i - 1][j - 1] # NO NEED FOR MAX HERE!! You can't have longer subsequence with a shorter string!
现在,要回答您的问题,如果您不使用动态编程(或者您曾经使用过并且遇到过最糟糕的情况,那就是没有重叠的子问题),那么您做不到比LCS x二次时间更好的了。
否则
您可以做的最优化是添加另一层动态编程。
假设采用自上而下的方法,请不要擦除包含2个子字符串之间的LCS的映射,这样您就可以在以后的计算中重用子问题
Python类似伪代码:
seq_lcs_map = map()
def computeLCS(str1, str2):
if str1.empty() or str2.empty():
return 0
try:
return seq_lcs_map[(str1,str2)]
catch:
try:
seq_lcs_map[(str2,str1)]
catch:
if str1[0] == str2[0]:
seq_lcs_map[(str1,str2)] = 1 + computeLCS(str1[1:], str2[1:])
else:
seq_lcs_map[(str1,str2)] = max(computeLCS(str1[1:],str2), computeLCS(str1,str2[1:]))
seq_lcs_map[(str2, str1)] = seq_lcs_map[(str1, str2)]
return seq_lcs_map[(str1, str2)]
def batch_LCS(l1, l2):
for i in l1:
for j in l2:
try:
seq_lcs_map[(i,j)]
catch:
try:
seq_lcs_map[(j,i)]
catch:
seq_lcs_map[(i,j)] = seq_lcs_map[(j,i)] = computeLCS(i,j)
注意:映射键有点冗余,但是比起尝试获得最佳效果,更好地捕捉一些奇怪的边缘情况