5. 最长回文串

问题描述

https://leetcode.cn/problems/longest-palindromic-substring/description/

解题思路

如果一个字符串是回文串,那么它左边接上一个字符,右边接上一个字符,如果这两个字符相等,那这个长字符串必然是回文串。

所以,我们可以从原来的状态推导出现在的状态。所以这是个动态规划题目。

我们用dp[left_ptr][right_ptr] 代表了s[left_ptr: right_ptr+1]是否为回文串。从小串往大串递推即可。

代码

class Solution:
    def longestPalindrome(self, s: str) -> str:
        # dp[left_ptr][right_ptr] 代表了s[left_ptr: right_ptr+1]是否为回文串
        n = len(s)
        dp = [[False for i in range(n+1)] for j in range(n+1)]
        for i in range(n+1):
            dp[i][i] = True
        res_begin = 0
        max_len = 1
        for length in range(2, n+1):
            for left_ptr in range(n):
                right_ptr = left_ptr+length-1
                if right_ptr >= n:
                    # 右边界越界
                    break
                if s[left_ptr] != s[right_ptr]:
                    dp[left_ptr][right_ptr] = False
                elif right_ptr - left_ptr < 3:
                    dp[left_ptr][right_ptr] = True
                else:
                    dp[left_ptr][right_ptr] = dp[left_ptr+1][right_ptr-1]
                if dp[left_ptr][right_ptr] and right_ptr-left_ptr+1>max_len:
                    max_len = right_ptr-left_ptr+1
                    res_begin = left_ptr
        return s[res_begin: res_begin+max_len]

 代码二:

class Solution:
    def longestPalindrome(self, s: str) -> str:
        length = len(s)
        dp = [[False for i in range(length+1)] for j in range(length+1)]
        for i in range(length+1):
            dp[i][i] = True
        maxs_length = 1
        left_res, right_res = 0, 1
        for str_len in range(2, length+1):
            for left_idx in range(length):
                right_idx = str_len + left_idx - 1
                if right_idx >= length:
                    continue
                if s[left_idx] != s[right_idx]:
                    dp[left_idx][right_idx] = False
                elif str_len < 3:
                    dp[left_idx][right_idx] = True
                else:
                    dp[left_idx][right_idx] = dp[left_idx+1][right_idx-1]
                if dp[left_idx][right_idx] and maxs_length < str_len:
                    maxs_length = str_len
                    left_res, right_res = left_idx, right_idx+1
        return s[left_res: right_res]

其实,dp的做法就是保存了状态。

我们这题也可以用“中心扩展法”。其实这是另外一种层面的dp,因为它的思想是dp的,即保存了状态。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        def midExpand(s, left, right):
            while 0<=left and right < len(s) and s[left] == s[right]:
                left -= 1
                right += 1
            return s[left+1: right]
        res = s[0]
        for i in range(len(s)):
            s1 = midExpand(s, i, i)
            if len(s1) > len(res):
                res = s1
            s2 = midExpand(s, i, i+1)
            if len(s2) > len(res):
                res = s2
        return res

 2024二刷

class Solution:
    def longestPalindrome(self, s: str) -> str:
        length = len(s)
        dp = [[False for i in range(length+1)] for j in range(length+1)]
        # dp[i][j]为s[i:j+1]是否为回文串
        for i in range(length+1):
            dp[i][i] = True
        res = s[0]
        for str_len in range(2, length+1):
            for left_ptr in range(length):
                right_ptr = str_len + left_ptr - 1
                if right_ptr >= length:
                    break
                if s[left_ptr] != s[right_ptr]:
                    dp[left_ptr][right_ptr] = False
                elif right_ptr - left_ptr < 3:
                    dp[left_ptr][right_ptr] = True
                else:
                    dp[left_ptr][right_ptr] = dp[left_ptr+1][right_ptr-1]
                if dp[left_ptr][right_ptr] and right_ptr-left_ptr+1>len(res):
                    res = s[left_ptr: right_ptr+1]
        return res

 

posted @ 2023-01-15 18:17  BJFU-VTH  阅读(20)  评论(0编辑  收藏  举报