5 最长回文子串(区间 dp)
1. 问题描述:
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-palindromic-substring/
2. 思路分析:
这道题目类似于最长回文子序列的问题,而子串的限制要求字符串是连续的,但是也是类似的思路,因为同样是求解一个区间中满足某个限制的问题,所以可以使用区间 dp 来解决,只是在状态计算的时候会有些不一样,只需要细微调整一下即可,对于长度为 1 的子串那么回文串的长度为 1;对于长度为 2 的子串判断 s[i] == s[j],相等则为 2;长度大于 2 的子串判断 s[i] == s[j] 并且 f(i + 1,j - 1) 大于 0 说明 s[i + 1:j - 1] 才是回文串。
3. 代码如下:
python(超时):
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
f = [[0] * (n + 10) for i in range(n + 10)]
res = ""
# 经典的区间dp框架, 枚举长度
for l in range(1, n + 1):
# 枚举起点i
i = 0
while i + l - 1 < n:
# j为当前起点为i长度为l的区间终点
j = i + l - 1
if l == 1:
f[i][j] = 1
elif l == 2:
if s[i] == s[j]:
f[i][j] = 2
else:
if s[i] == s[j] and f[i + 1][j - 1]:
f[i][j] = f[i + 1][j - 1] + 2
if f[i][j] > len(res):
res = s[i: j + 1]
i += 1
return res
go:
package main
import "fmt"
func longestPalindrome(s string) string {
n := len(s)
f := make([][]int, n+10)
for i := 0; i < n+10; i++ {
f[i] = make([]int, n+10)
}
res := ""
for l := 1; l <= n; l++ {
i := 0
for ; i+l-1 < n; i++ {
j := i + l - 1
if l == 1 {
f[i][j] = 1
} else if l == 2 {
if s[i] == s[j] {
f[i][j] = 2
}
} else if s[i] == s[j] && f[i+1][j-1] > 0 {
f[i][j] = f[i+1][j-1] + 2
}
if f[i][j] > len(res) {
res = s[i : j+1]
}
}
}
return res
}
中心扩展解法:
python:
class Solution:
def get(self, i: int, j: int, s: str, res: str):
t = ""
while i >= 0 and j < len(s) and s[i] == s[j]:
t = s[i: j + 1]
i -= 1
j += 1
if len(t) > len(res):
res = t
return res
def longestPalindrome(self, s: str) -> str:
n = len(s)
res = ""
for i in range(n):
res = self.get(i, i, s, res)
res = self.get(i, i + 1, s, res)
return res
go:
package main
import "fmt"
func get(i int, j int, s string, res string) string {
t := ""
for i >= 0 && j < len(s) && s[i] == s[j] {
t = s[i : j+1]
i -= 1
j += 1
}
if len(t) > len(res) {
res = t
}
return res
}
func longestPalindrome(s string) string {
n := len(s)
res := ""
for i := 0; i < n; i++ {
// 若当前的回文串为奇数
res = get(i, i, s, res)
// 若当前的回文串为偶数
res = get(i, i+1, s, res)
}
return res
}