Skip to content

230810 Longest Common Subsequence

【题意】: 纯 LCS

【 Excepted 】:

  • Time Complexity : O(|str1|*|str2|)
  • Auxiliary Space: O(|str1|*|str2|)

关键点在于理解 “暴力递归” 的版本。后续的三个优化是模板套路。

Python3

【暴力递归 - 10/1120】:

py
class Solution:
    def lcs(self,x,y,s1,s2):
        if x < 1 or y < 1:
            return 0
        if s1[x-1] == s2[y-1]:
            return 1 + self.lcs(x-1, y-1, s1, s2)
        return max(
            self.lcs(x-1, y, s1, s2),
            self.lcs(x, y-1, s1, s2)
        )

【优化 1 - 递归填表 1010/1120】:

py
class Solution:

    def process(self, x, y, s1, s2, dp):
        if x < 0 or y < 0:
            return 0

        if dp[x][y] != -1:
            return dp[x][y]

        if s1[x] == s2[y]:
            dp[x][y] = 1 + self.process(x-1, y-1, s1, s2, dp)
            return dp[x][y]

        dp[x][y] = max(
            self.process(x-1, y, s1, s2, dp),
            self.process(x, y-1, s1, s2, dp)
        )

        return dp[x][y]

    def lcs(self,x,y,s1,s2):
        dp = [ [-1] * y for _ in range(x) ]
        return self.process(x-1, y-1, s1, s2, dp)

【优化 2 - 非递归填表(动态规划)】:

py
class Solution:
    #Function to find the length of longest common subsequence in two strings.
    def lcs(self,x,y,s1,s2):
        dp = [ [0] * (y+1) for _ in range(x + 1) ]

        for i in range(1, x+1):
            for j in range(1, y+1):
                i1, i2 = i-1, j-1
                if s1[i1] == s2[i2]:
                    dp[i][j] = 1 + dp[i-1][j-1]
                else:
                    dp[i][j] = max(
                        dp[i-1][j],
                        dp[i][j-1],
                    )
        return dp[x][y]

【优化 3 - 优化表结构】:

py
class Solution:
    def lcs(self,x,y,s1,s2):
        curr = [0] * (y+1)
        prev = [*curr]

        for i in range(1, x+1):
            for j in range(1, y+1):
                i1, i2 = i-1, j-1
                if s1[i1] == s2[i2]:
                    curr[j] = 1 + prev[j-1]
                else:
                    curr[j] = max(
                        prev[j],
                        curr[j-1],
                    )
            prev = [*curr]
        return prev[y]