【leetCode】最长回文子串

258 阅读2分钟

题目

最长回文子串

读题

  • 题目是找出一个字符串串里的最大回文子串
  • 回文串就是正着读和反着读都一样的字符串,比如abcba
  • 子串就是字符串中的一部分,且这部分是连续的。区别于子序列。

解题

解题思路

暴力法解题

一开始啥都不用想,使用暴力法解题。主要思路为:

  1. 找出所有可能的子串
  2. 遍历子串,判断子串是否是回文字符串,是的记住子串
  3. 最大长度的回文子串可能由多个,返回任意一个就行了
  4. 可以使用剪枝算法减少穷举次数
package main
​
import "fmt"func getMaxSubCount(s string) string {
    length := len(s)
    if length <= 1 {
        return s
    }
    var maxSubStr string
    // 遍历所有可能的子串
    for i := 0; i < length-1; i++ {
        // 当前子串长度不大于已知的最大回文子串,则直接跳过
        for j := i + len(maxSubStr); j < length; j++ {
            if check(s[i : j+1]) {
                maxSubStr = s[i : j+1]
            }
        }
    }
    return maxSubStr
}
​
// 判断是否是回文串
func check(s string) bool {
    length := len(s)
    if length <= 1 {
        return true
    }
    mid := length / 2
    for i := 0; i < mid; i++ {
        if s[i] != s[length-1-i] {
            return false
        }
    }
    return true
}
​
func main() {
    s := "ababa"
    fmt.Println(getMaxSubCount(s))
}

动态规划

子串和子序列问题大都与动态规划有关,这里尝试使用动态规划解题。

  1. 假设已知一个字符串s,并且我们知道它的最大回文子串。

  2. 现在字符串s右边拼接一个字符c,那么它的最大回文子串会有什么变化呢?

    1. 举个例子:abacd + d = abacdd,这种情况已知aba是之前的最大子串(长度为3),现在为判断字符d的影响,变成了判断新字符串的后缀子串时候是回文子串。与暴力法没啥区别,遂放弃了。
  3. 换种角度,驾驶已知长度为a的回文子串,我们要找长度为a+1的子串是不是简单多了,就只需看该子串左右两边的字符是否满足就行了。

package main
​
import (
    "fmt"
)
​
func getMaxSubCount(s string) string {
    length := len(s)
    if length <= 1 {
        return s
    }
    var maxSubStr string
    // memory[i][j]=1表示字符串s[j:j+i]是回文串
    memory := make([][]int, length+1)
    for i := 0; i <= length; i++ {
        memory[i] = make([]int, length)
    }
    // 长度<=1子串的都是回文串
    maxSubStr = s[:1]
    for i := 0; i < length; i++ {
        memory[0][i] = 1
        memory[1][i] = 1
    }
    // 逐次寻找长度为i的回文子串
    for i := 2; i <= length; i++ {
        flag := false
        for j := 0; j < length-i+1; j++ {
            // 如果s[j+1:(j+1)+(i-2)+1]是个回文串(长度为i-2),且s[j]==s[j+i-1],那么s[j:j+i]也是回文串
            if memory[i-2][j+1] == 1 && s[j] == s[j+i-1] {
                memory[i][j] = 1
                // 记住最大子串
                if !flag {
                    maxSubStr = s[j : j+i]
                    flag = true
                }
            }
        }
    }
    return maxSubStr
}
​
func main() {
    s := "babad"
    fmt.Println(getMaxSubCount(s))
}