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