最长公共子序列(二)
Last updated
Last updated
问题简述
给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列。
思路:动态规划
定义 dp[i][j]
表示 s1[:i]
和 s2[:j]
的最长公共子序列;
本题要求输出最长子序列,可以通过 dp
矩阵逆推;
参考递推表格,从右下角一步一步向左上角推进;
class Solution:
def LCS(self , s1: str, s2: str) -> str:
m, n = len(s1), len(s2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
# r1 = dp[i - 1][j]
# r2 = dp[i][j - 1]
# r3 = dp[i - 1][j - 1] + int(s1[i - 1] == s2[j - 1])
# dp[i][j] = max(r1, r2, r3)
# 推荐下面的写法
# 表明 dp[i - 1][j] 和 dp[i][j - 1] 至多比 dp[i][j - 1] 大 1
if s1[i - 1] == s2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
ret = []
i, j = m, n
while i > 0 and j > 0:
if s1[i - 1] == s2[j - 1]:
ret.append(s1[i - 1])
i -= 1
j -= 1
else:
# 因为题目说明只有一个解,所以其实不会存在 dp[i - 1][j] == dp[i][j - 1] 的情况;
# 换言之,如果存在 dp[i - 1][j] == dp[i][j - 1],即有多组解;
if dp[i - 1][j] > dp[i][j - 1]:
i -= 1
else:
j -= 1
ret = ''.join(ret[::-1]) # 逆序
return ret if ret else '-1'