给你一个字符串 s
,找到 s
中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。
示例 2:
输入: s = "cbbd"
输出: "bb"
提示:
1 <= s.length <= 1000
s
仅由数字和英文字母组成
解答:
解法一:动态规划
这道题使用动态规划算法能够减少算法的时间复杂度,我们首先初始化一个dp数组,用来存储动态规划的结果,双层for循环进行遍历,外层代表最长回文子串的长度,内层对每一个字符进行遍历,首先,l=0时表示每一个字符自身都是回文,l=1时,需要判断当前两个字符是否相同,l>=2时判断字符是否相同,相同则将dp数组更新,如果上次前一个位置的字符是回文,则此时也是回文,最后,更新最长回文字符串。
func longestPalindrome(s string) string {
n := len(s)
dp := make([][]bool, n)
for i,_ := range dp {
dp[i] = make([]bool, n)
}
ans := ""
for l:=0; l<n; l++ { // l为本次循环遍历的子串长度
for i:=0; i+l<n; i++ {
j := i+l
if l == 0 {
dp[i][j] = true
} else if l == 1 {
dp[i][j] = (s[i] == s[j])
} else {
dp[i][j] = (s[i] == s[j] && dp[i+1][j-1])
}
if dp[i][j] && l+1 > len(ans) {
ans = s[i:j+1]
}
}
}
return ans
}
解法二:中心扩展 中心扩展的思想是遍历每一个字符,计算以该字符为中心的最长回文串长度,定义一个compare函数用来计算最长回文串,由于有两种情况:"aba"式的回文,即s[i]!=s[i+1]和"abba"式的回文,即s[i]==s[i+1],所以要分两种情况调用两次compare,返回最长的子串。
unc longestPalindrome(s string) string {
if s == "" {
return ""
}
l, r := 0, 0
maxlen := 0
for i := 0; i < len(s); i++ {
l1, r1 := compare(s, i, i+1)
l2, r2 := compare(s, i, i)
if r1-l1+1 > maxlen {
maxlen = r1 - l1 + 1
l = l1
r = r1
}
if r2-l2+1 > maxlen {
maxlen = r2 - l2 + 1
l = l2
r = r2
}
}
return s[l : r+1]
}
func compare(s string, i int, j int) (int, int) {
for i >= 0 && j < len(s) && s[i] == s[j] {
i -= 1
j += 1
}
return i + 1, j - 1
}