主要是如何输出结果的字符串,而不是简单的最长的公共序列的长度。
- 这里的1+LCS(...)表示每次在数值上累加!
- 这里的比较max(value1, value2)表示对数值上的大小进行比较!
- 这里的s1[i]+LCS(...)表示在字符串上的累加!
- 这里对len(str1)和len(str2) 是对str1和str2的(结果字符串)的长度进行比较
因为上面的递归 会导致重复的计算
所以通过记录路径 来优化时间 该memo用来记录递归路上的 所有存下的best match string
def LCS(i, j, s1, s2, memo):
if i >= len(s1) or j >= len(s2):
return ""
if s1[i] == s2[j]:
if memo[i+1][j+1] == "": #如果两个字符相同
memo[i+1][j+1] = LCS(i+1, j+1, s1, s2, memo)
memo[i][j] = s1[i]+memo[i+1][j+1]
return s1[i]+LCS(i+1, j+1, s1, s2, memo)
else:
str1 = memo[i][j+1]
str2 = memo[i+1][j]
if memo[i][j+1] == "":
str1 = LCS(i, j+1, s1, s2, memo)
if memo[i+1][j] == "":
str2 = LCS(i+1, j, s1, s2, memo)
if len(str1) > len(str2):
memo[i][j] = str1
return str1
else:
memo[i][j] = str2
return str2
def lcs(s1, s2):
memo = [["" for j in range(len(s2)+1)] for i in range(len(s1)+1)]
value = LCS(0, 0, s1, s2, memo)
print(memo)
return value
s1 = "Look at me, I can fly!"
s2 = "Look at that, it's a fly"
print(lcs(s1, s2))
这样写有一个bug,就是
s1 = "abcdefghijklmnopqrstuvwxyz"
s2 = "ABCDEFGHIJKLMNOPQRSTUVWXYS"
print(lcs(s1, s2))
的结果是跑不出来的。
但是
s1 = "abc"
s2 = "ABC"
print(lcs(s1, s2))
是能跑出来的。
所以代码的逻辑并没有问题。
其实并不是跑不出来,只是跑的太慢了 = 优化没有起到作用。
这个的原因是,我在前面的代码中初始化为“”。如果确实是没有公共部分的时候,也为“”,所以memo的初始情况和两个字符串没有公共部分,这两个点弄混淆了,继而可以更改使初始化为0,与没公共部分的“”区别开来。
def LCS(i, j, s1, s2, memo):
if i >= len(s1) or j >= len(s2):
return ''
if s1[i] == s2[j]:
if memo[i+1][j+1] == 0: #如果两个字符相同
memo[i+1][j+1] = LCS(i+1, j+1, s1, s2, memo)
memo[i][j] = s1[i]+memo[i+1][j+1]
return memo[i][j]
else:
str1 = memo[i][j+1]
str2 = memo[i+1][j]
if memo[i][j+1] == 0:
str1 = LCS(i, j+1, s1, s2, memo)
if memo[i+1][j] == 0:
str2 = LCS(i+1, j, s1, s2, memo)
if len(str1) > len(str2):
memo[i][j] = str1
return str1
else:
memo[i][j] = str2
return str2
def lcs(s1, s2):
memo = [[0 for j in range(len(s2)+1)] for i in range(len(s1)+1)]
value = LCS(0, 0, s1, s2, memo)
print(memo)
return value
s1 = "Look at me, I can fly!"
s2 = "Look at that, it's a fly"
print(lcs(s1, s2))