最长公共子序列,动态规划,时间O(mn),空间O(min(m,n)*k),k为最长公共子序列长度

类似于:https://www.nowcoder.com/discuss/388075528203378688
只是该问题的状态表示最长公共子序列本身而非长度。

class Solution:
    def LCS(self , s1: str, s2: str) -> str:
        if not s1 or not s2: return -1
        if len(s1) > len(s2):
            s1, s2 = s2, s1          # 让s1表示短串
        m, n = len(s1), len(s2)
        dp = ['']*(m+1)              # 根据短串的长度构造dp
        for i in range(n):
            pre_dp = dp[0]           # 初始的[i-1][j-1]位置的dp,为dp[0],一直为空,便于算边缘位置
            for j in range(m):
                if s1[j] == s2[i]:     # 相等        
                    tmp = dp[j+1]      # 记录下一个[i-1][j-1]位置的dp备用,为之前的dp[j+1]
                    dp[j+1] = pre_dp + s1[j] # 状态转移
                    pre_dp = tmp
                else:
                    pre_dp = dp[j+1]   # 记录下一个[i-1][j-1]位置的dp备用,为之前的dp[j+1]
                    dp[j+1] = dp[j+1] if len(dp[j+1]) > len(dp[j]) else dp[j] # 状态转移
        if dp[-1]:  # 可能为''
            return dp[-1]
        else: 
            return -1