代码随想录算法训练营第五十七天| 647. 回文子串,516. 最长回文子序列,5. 最长回文子串

647. 回文子串

题目链接:回文子串

动态规划

s = ‘cbabc’,如果判断这是否是回文串,那么最好的方式是

  • 判断中间的字符串s[1:(len(s)-1]是否为回文串
  • 判断s[0]s[len(s)-1]是不是相等
  • 都是那么s就是回文串

所以这个遍历的顺序应该是如果s[i]s[j]相等的,那么dp[i][j]就应该等于左下方(中间部分)的判断也就是dp[i+1][j-1]

class Solution:
    def countSubstrings(self, s: str) -> int:
        # dp[i][j] = 以s[i:j]是否为回文子串。
        dp = [[False]*len(s) for _ in range(len(s))]
        dp[0][0] = True
        res = 1
        for i in range(1,len(s)):
            dp[i][i] = True
            res += 1
            if s[i-1] == s[i]:
                res += 1
                dp[i-1][i] = True
        
        for j in range(2,len(s)):
            for i in range((j-1)):
                if s[j] == s[i]:
                    dp[i][j] = dp[i+1][j-1]
                    if dp[i][j] == True:
                        res += 1
        return res

双指针

s = ‘cbabc’

  • 以中心点a为起点
  • 判断a, bab, cbabc
  • 以ba为起点
  • 判断ba, cbab
  • 以ab为起点
  • 判断ab, babc
  • 以此类推

这里只有一个while主要是因为他是从中心点往外扩散的,如果中心点就不是回文串了,那外面肯定不是,也不用出去了。

class Solution:
    def countSubstrings(self, s: str) -> int:
        def test(s,i,j):
            res = 0
            while i>=0 and j<len(s) and (s[i] == s[j]):
                i -= 1
                j += 1
                res += 1
            return res
        
        res = 0
        for i in range(len(s)):
            res += test(s,i,i)
            res += test(s,i,i+1)
        return res

516. 最长回文子序列

题目链接:最长回文子序列

s = ‘bbbab’
和上一题一样,

  • 如果s[i]s[j]相等的,那么dp[i][j]就应该等于左下方(中间部分)的判断也就是dp[i+1][j-1]+2
  • 如果不相等的那就看i-1j或者ij-1的最大值是多少。
  • 顺便我自己的代码去管dp[i-1][i]纯粹是多此一举,因为递推公式能管到。
class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        # dp[i][j] = i到j内的最长的回文子序列长度.
        dp = [[0]*len(s) for _ in range(len(s))]
        dp[0][0] = 1
        for i in range(1,len(s)):
            dp[i][i] = 1
            if s[i-1] == s[i]:
                dp[i-1][i] = 2
            else:
                dp[i-1][i] = 1
        
        for j in range(2,len(s)):
            for i in range((j-1),-1,-1):
                if s[i] == s[j]:
                    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][-1]

5. 最长回文子串

题目链接:最长回文子串

用了第一题的代码,把回文子串的长度都记下来,找出最大的那个。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        dp = [[False]*len(s) for _ in range(len(s))]
        dp[0][0] = True
        diff = 0
        res = s[0]
        for i in range(1,len(s)):
            dp[i][i] = True
            if s[i-1] == s[i]:
                diff = 2
                res = s[(i-1):(i+1)]
                dp[i-1][i] = True
        
        
        for j in range(2,len(s)):
            for i in range((j-1)):
                if s[j] == s[i]:
                    dp[i][j] = dp[i+1][j-1]
                    if dp[i][j] == True and (j-i+1>diff):
                        diff = j-i+1
                        res = s[i:(j+1)]
        return res
05-10 21:58