5. 最长回文子串 中等
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
示例 3:
输入:s = "a"
输出:"a"
示例 4:
输入:s = "ac"
输出:"a"
提示:
- 1 <= s.length <= 1000
- s 仅由数字和英文字母(大写和/或小写)组成
代码参考l
package main
import "fmt"
func main() {
fmt.Println(badLongestPalindrome("babad")) // bab
fmt.Println(goodLongestPalindrome("babad")) // bab
fmt.Println(bestLongestPalindrome("babad")) // bab
}
//
// Manacher 马拉车算法
// O(N) 检测最长回文子串
//
func bestLongestPalindrome(s string) string {
if len(s) <= 1 {
return s
}
t := "#"
for _, r := range s {
t += string(r) + "#" // 统一将 偶数串/奇数串 -> 奇数串
}
radius := make([]int, len(t)) // 每个位置的回文半径
maxCenter := 0 // 到目前为止最长回文串的中心位置
maxR := 0 // 到目前位置最长回文串的右边界索引
stopCenter := 0
maxRadius := 0
for i := 0; i < len(t); i++ {
mirror := 2*maxCenter - i
if i < maxR { // 没有超过最大右边界
radius[i] = min(radius[mirror], maxR-i) // 取 [i,mx] 与 i'半径 的最小值
}
// 以 i 为中心不断扩充半径,向左右两侧探测回文
// 不要以为这里复杂度为 O(N)
// 若上边 radius[i] = radius[i'],则不会再进入循环扩张半径
for i+1+radius[i] < len(t) && i-1-radius[i] >= 0 && t[i-1-radius[i]] == t[i+1+radius[i]] {
radius[i]++
}
// 超出了边缘
if i+radius[i] > maxR {
maxR = i + radius[i]
maxCenter = i
}
if radius[i] > maxRadius {
maxRadius = radius[i]
stopCenter = i
}
}
l := stopCenter/2 - maxRadius/2 // t->s,索引取中
r := l + maxRadius - 1 // 减掉自身
return string(s[l : r+1]) // bingo
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
//
// Golang 的题解中不要使用全局作用域变量,OJ 每个 case 不会予以清零
// O(N^2) 复杂度
//
func goodLongestPalindrome(s string) string {
runes := []rune(s)
var maxLen int
var maxSubStr string
for i := range runes {
length, str := spread(runes, i, i, maxLen) // aba
if length > maxLen {
maxLen = length
maxSubStr = str
}
length, str = spread(runes, i, i+1, maxLen) // abba
if length > maxLen {
maxLen = length
maxSubStr = str
}
}
return maxSubStr
}
// 以中心点向两侧扩散,获取当前字符为中心的最大回文串
func spread(runes []rune, l, r int, curMaxLen int) (length int, subStr string) {
length = curMaxLen
for ; l >= 0 && r <= len(runes)-1 && runes[l] == runes[r]; l, r = l-1, r+1 {
if r-l+1 >= length { // <= 是因为 OJ 认为 babad 的答案是 aba 而非 bab
length = r - l + 1
subStr = string(runes[l : r+1])
}
}
return
}
//
// O(N^3) 复杂度
//
func badLongestPalindrome(s string) string {
runes := []rune(s)
n := len(runes)
if n <= 1 {
return s
}
maxLen := 0
maxL, maxR := 0, 0
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
if isPalindrome(runes[i:j+1]) && j-i+1 > maxLen {
maxLen = j - i + 1
maxL, maxR = i, j
}
}
}
return string(runes[maxL : maxR+1]) // 注意对空字符串,转换为 "\u0000"
}
// O(N) 判断是否为回文字符串
func isPalindrome(runes []rune) bool {
l, r := 0, len(runes)-1
for l <= r {
if runes[l] != runes[r] {
return false
}
l++
r--
}
return true
}
最后编辑: kuteng 文档更新时间: 2021-06-05 10:16 作者:kuteng