Leetcode题目【回文子串+回文子序列】

目录

  • 647. 回文子串
  • 5. 最长回文子串
  • 516. 最长回文子序列

647. 回文子串

  • 作为一个回文子串,主打的就是连续子串两边对称
  • 所以递推公式怎么想呢?子问题dp是一个成型的回文子串,当我左右两边加上相同的字符,才会再次构成当前的回文子串!

【dp数组的定义】:

  • 题目是求回文子串的个数。
  • 如果直观上用dp的子状态来存储子问题的回文串个数,当i、j位置上元素相等时,那此时确实是子问题的dp值加1,但是没法判断子问题它是不是回文串呀。
  • 所以这里的dp设计的是,当前子串是不是回文串,而不是当前子串包含的回文串的数量 。至于最后要求的数量,直接弄个变量进行累加就行了,dp数组都存好了是不是回文串,就不愁数量的计算了。
    Leetcode题目【回文子串+回文子序列】_第1张图片
class Solution:
    def countSubstrings(self, s: str) -> int:
        size = len(s)
        dp = [[0]*size for i in range(size)]  #开始时假设任意子串都不是回文的
        res = 0 

        for i in range(size-1, -1, -1): #i从大到小遍历
            for j in range(i, size): #j小于i的就不用考虑了,j从小到大遍历
                if s[i]==s[j]: #两边相等
                    if j-i<=1 or dp[i+1][j-1]==1: #长度是1或2,或子问题是回文串
                        dp[i][j] = 1
                        res += 1
        return res          

5. 最长回文子串

和上题本质一样,就是加个变量记录一下最大长度,记录下最大长度的左右边界

class Solution:
    def longestPalindrome(self, s: str) -> str:
        size = len(s)
        dp = [[0]*size for i in range(size)]  #开始时假设任意子串都不是回文的
        maxLen = 1
        l,r = 0,0

        for i in range(size-1, -1, -1): #i从大到小遍历
            for j in range(i, size): #j小于i的就不用考虑了,j从小到大遍历
                if s[i]==s[j]: #两边相等
                    if j-i<=1 or dp[i+1][j-1]==1: #只有1个或2个字符,或者子问题是回文的
                        dp[i][j] = 1
                        if j-i+1>maxLen: #更新最优值
                            maxLen = j-i+1
                            l,r = i,j

        return s[l:r+1]

516. 最长回文子序列

  • 这个题既然要求长度,那我们就让dp存长度值好了啦,一开始默认是0
  • 至于中间子问题是不是回文的,我不关心,因为我只考虑长度,即使中间不是回文的,那我只要两边是相等的,这俩就已经构成子序列,就有长度值啦
  • 和1143.最长公共子序列那个题类似,只要是子序列就涉及到退步,加个退步就解决了子序列和子串之间的差异。
class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        size = len(s)
        # dp存储当前子序列最长回文串长度值
        dp = [[0]*size for i in range(size)]

        for i in range(size-1, -1, -1):
            for j in range(i, size):
                if s[i]==s[j]: #两边相等
                    if j-i<=1: #长度只有1或2
                        dp[i][j] = j-i+1 
                    else:
                        dp[i][j] = dp[i+1][j-1]+2 #超过两个数,此时就有有子问题了
                else: #两边不相等,就要退步了
                    dp[i][j] = max(dp[i][j-1], dp[i+1][j])
        
        return dp[0][size-1]

你可能感兴趣的:(#,Leetcode,刷题,leetcode,算法,回文,回文子串,回文子序列)