Skip to content

230719 - Longest Palindromic Subsequence

  • 【题意】 LCS 最长公共子序列 问题

首先,区分两个概念:

  • 子序列(Subsequence):不需要连续
  • 子字符串(substring): 需要连续

然后,这道题和昨天的题目本质是一样的,都是最长公共子序列问题。 只不过这道题问的是回文子序列,需要 “脑筋转一下” —— 求字符串和反转字符串的最长公共子序列。

没什么好说的,挣扎了一个多小时,然后放弃了。

Python3 代码

【评论区 - 递归 ❌】:

py
class Solution:
    def lcs(self, i, j, A, B):
        if i < 0 or j < 0:
            return 0
        if A[i] == B[j]:
            return 1 + self.lcs(i-1, j-1, A, B)
        return max(self.lcs(i-1, j, A, B), self.lcs(i, j-1, A, B))

    def longestPalinSubseq(self, S):
	    n = len(S)
	    return self.lcs(n-1, n-1, S, S[::-1])

【评论区 - 递归填表】:

py
class Solution:
    def lcs(self, i, j, A, B, dp):
        if i < 0 or j < 0:
            return 0
        if dp[i][j] != -1:
            return dp[i][j]
        if A[i] == B[j]:
            return 1 + self.lcs(i-1, j-1, A, B, dp)
        dp[i][j] = max(self.lcs(i-1, j, A, B, dp), self.lcs(i, j-1, A, B, dp))
        return dp[i][j]

    def longestPalinSubseq(self, S):
	    n = len(S)
	    dp = [[-1] * n for _ in range(n)]
	    return self.lcs(n-1, n-1, S, S[::-1], dp)

【评论区 - 动态规划】:

py
class Solution:
    def longestPalinSubseq(self, S):
	    n = len(S)
	    RS = S[::-1]
	    dp = [[0] * (n+1) for _ in range(n+1)]
	    for i in range(1, n+1):
	        for j in range(1, n+1):
	            if (S[i-1] == RS[j-1]):
	                dp[i][j] = 1 + dp[i-1][j-1]
                else:
                    dp[i][j] = max(dp[i][j-1], dp[i-1][j])
	    return dp[n][n]

【评论区 - 动态规划优化空间】:

py
class Solution:
    def longestPalinSubseq(self, S):
	    n = len(S)
	    RS = S[::-1]
	    prev = [0] * (n+1)
	    curr = [0] * (n+1)

	    for i in range(1, n+1):
	        for j in range(1, n+1):
	            if S[i-1] == RS[j-1]:
	                curr[j] = 1 + prev[j-1]
                else:
                    curr[j] = max(curr[j-1], prev[j])
            prev = [*curr]
	    return prev[n]