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

文章介绍了如何使用动态规划解决回文子串、最长回文子串和最长回文子序列的问题,通过遍历字符串和比较字符,结合子问题的状态转移矩阵,确定回文性质并计算最长长度。
摘要由CSDN通过智能技术生成

647. 回文子串

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

【dp数组的定义】:

  • 题目是求回文子串的个数。
  • 如果直观上用dp的子状态来存储子问题的回文串个数,当i、j位置上元素相等时,那此时确实是子问题的dp值加1,但是没法判断子问题它是不是回文串呀。
  • 所以这里的dp设计的是,当前子串是不是回文串,而不是当前子串包含的回文串的数量 。至于最后要求的数量,直接弄个变量进行累加就行了,dp数组都存好了是不是回文串,就不愁数量的计算了。
    在这里插入图片描述
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上的最长回文子串问题。 方法一是使用扩展中心法优化,即从左向右遍历字符串,找到连续相同字符组成的子串作为扩展中心,然后从该中心向左右扩展,找到最长的回文子串。这个方法的时间复杂度为O(n²)。\[1\] 方法二是直接循环字符串,判断子串是否是回文子串,然后得到最长回文子串。这个方法的时间复杂度为O(n³),效率较低。\[2\] 方法三是双层for循环遍历所有子串可能,然后再对比是否反向和正向是一样的。这个方法的时间复杂度也为O(n³),效率较低。\[3\] 综上所述,方法一是解决LeetCode最长回文子串问题的最优解法。 #### 引用[.reference_title] - *1* [LeetCode_5_最长回文子串](https://blog.csdn.net/qq_38975553/article/details/109222153)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode-最长回文子串](https://blog.csdn.net/duffon_ze/article/details/86691293)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [LeetCode 第5题:最长回文子串(Python3解法)](https://blog.csdn.net/weixin_43490422/article/details/126479629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值