最长公共子序列(Longest-Common Subsequence)
问题描述: 给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。
最长公共子序列的定义:最长公共子序列问题是在一组序列中找到最长公共子序列(不同于公共子串,LCS不需要是连续的子串)
输入: 给出字符串”ABCD”和字符串“EDCA”
输出: 1
"""
dp[i - 1][j - 1] + 1 if s1[i] == s2[j]
dp[i][j] = max(dp[i -1][j], dp[i][j - 1]) others
"""
def LCS(s1, s2):
def show(mat):
for i in mat: print(i)
if not s1 or not s1: return 0
m, n = len(s1), len(s2)
# tmp is a obejct
tmp = [0, ] * n
dp = []
# deep copy
for i in range(m):
dp.append(tmp.copy())
# 1. 处理S1与S2[0]的情况
index = [0, ]
for i in range(m):
if s1[i] == s2[0]:
index[0] = i
break
for j in range(index[0], m):
dp[j][0] = 1
# 2. 处理S1[0]与S[1]的情况
for x in range(n):
if s1[0] == s2[x]:
index[0] = x
break
for y in range(index[0], n):
dp[0][y] = 1
# dp state
# show(dp)
# 3. 处理其余情况
for i in range(1, m):
for j in range(1, n):
if s1[i] == s2[j]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
show(dp)
return dp[m -1][n -1]
if __name__ == '__main__':
# sample1
s1 = 'blog.csdn.net'
s2 = 'csdn.blogt'
result = LCS(s1, s2)
print(result) # for sample1, the answer should be 6
# sample2
s1 = "A1BC2"
s2 = "ABB4C"
result = LCS(s1, s2)
print(result) # for sample2, the answer should be 3