美文网首页
最长回文子序列(IPS)

最长回文子序列(IPS)

作者: 小幸运Q | 来源:发表于2021-03-27 14:23 被阅读0次

dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度

  • 递归解法:

1.如果str的最后一个元素和第一个元素是相同的,则有:lps(0,n-1)=lps(1,n-2)+2;例如字符串序列“AABACACBA”,第一个元素和最后一个元素相同,其中lps(1,n-2)表示红色部分的最长回文子序列的长度;

2.如果str的最后一个元素和第一个元素是不相同的,则有:lps(0,n-1)=max(lps(1,n-1),lps(0,n-2));例如字符串序列“ABACACB”,其中lps(1,n-1)表示去掉第一元素的子序列,lps(0,n-2)表示去掉最后一个元素的子序列。

class Solution:
    def Circle(self,s,left,right):
        if(left==right):
            return 1
        elif(left>right):
            return 0
        else:
            if(s[left]!=s[right]):
                return max(self.Circle(s,left,right-1),self.Circle(s,left+1,right))
            else:
                return self.Circle(s,left+1,right-1)+2
    def longestPalindromeSubseq(self, s: str) -> int:
        if len(s)==1:
            return 1
        if s[0]==s[-1]:
            return self.Circle(s,1,len(s)-2)+2
        else:
            return max(self.Circle(s,1,len(s)-1),self.Circle(s,0,len(s)-2))
        return maxnum*2

  • 动态规划:

定义:d[i][j] 表示最大的回文字符串的长度

初始化:d[i][i] = 1 其他均为0,通过j \in [i+1,...)保持 i<j

i从length自高向低遍历,因为[i+1][j-1]需要上一级的结果,只求[i,j]范围内的解。i+1>j-1时因为j>=i+1,所以会落在(i+1,i)上,该点位于下半侧为0。

考虑两种情况:s[i] == s[j] d[i+1][j-1]+2s[i] != s[j] max(d[i+1][j], d[i][j-1])

如果[3][4]->[4][3],因为位于下半边的值默认为0,所以不会影响结果

最终结果: d[1][length] 其中n是字符串的长度

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        length=len(s)
        dp=[[0]*(length+1) for i in range(length+1)]
        for i in range(1,length+1):
            dp[i][i]=1
        for i in range(length,0,-1):
            for j in range(i+1,length+1):
                if s[i-1]==s[j-1]:
                    # 因为要求[i+1]所以必须得到上一层的解,所以要从高层length往底层1遍历
                    dp[i][j]=dp[i+1][j-1]+2
                else:
                    dp[i][j]=max(dp[i][j-1],dp[i+1][j])
        return dp[1][length]

状态压缩改进:

在dp[i+1][j-1]被覆盖之前用一个临时变量 temp 把它存起来,并把这个变量的值保留到计算 dp[i][j] 的时候

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        if len(s)==1:
            return 1
        dp=[0 for i in range(len(s))]
        for i in range(len(s)-2,-1,-1):
            dp[i]=1
            pre=0
            for j in range(i+1,len(s)):
                temp = dp[j];
                if s[i]==s[j]:
                    dp[j]=pre+2
                else:
                    dp[j]=max(dp[j-1],dp[j])
                pre=temp
        return dp[-1]

相关文章

网友评论

      本文标题:最长回文子序列(IPS)

      本文链接:https://www.haomeiwen.com/subject/kujshltx.html