5.最长回文子串
题目
给你一个字符串 s,找到 s 中最长的回文子串。
动态规划求解
- 确定 dp[] 含义:dp[i][j] 表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。
- 确定递推公式: 整体上是两种,就是s[i]与s[j]相等,s[i]与s[j]不相等这两种。 当s[i]与s[j]不相等,那没啥好说的了,dp[i][j]一定是false。 当s[i]与s[j]相等时,这就复杂一些了,有如下三种情况 情况一:下标i 与 j相同,同一个字符例如a,当然是回文子串 情况二:下标i 与 j相差为1,例如aa,也是回文子串 情况三:下标:i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了, 我们看i到j区间是不是回文子串就看aba是不是回文就可以了, 那么aba的区间就是 i+1 与 j-1 区间,这个区间是不是回文就看dp[i + 1][j - 1]是否为true。
- 确定 dp[] 如何初始化:dp[i][j]初始化为false
- 确定遍历顺序:由 dp[i+1][j-1] 推导出 dp[i][j],故 i 逆序遍历,j 顺序遍历
- 举例推导 aba
0,1,2
[f,f,f]
[f,f,f]
[f,f,f]
dp22 dp11 dp12 dp00 dp01 dp02 -> dp11
go
func longestPalindrome(s string) string {
dp := make([][]bool, len(s))
for i := range dp {
dp[i] = make([]bool, len(s))
}
var result string
for i := len(s) - 1; i >= 0; i-- {
for j := i; j < len(s); j++ {
if s[i] == s[j] {
if j-i <= 1 || dp[i+1][j-1] {
dp[i][j] = true
if j+1-i >= len(result) {
result = s[i : j+1]
}
}
}
}
}
return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23