leetcode:5. 最长回文子串
题目描述
给你一个字符串 s,找到 s 中最长的 回文 子串。
示例
输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。
题解
动态规划
-
状态定义
dp[i][j]定义为substring(i, j + 1)的子串是不是回文子串。 -
状态转移
- 如果
j - i <= 1,是回文子串。 - 如果
j - 1 == 2,判断这两个位置的字符是否相等。 - 如果
j - i > 2,那么dp[i][j] = (s.charAt(i) == s.charAt(j)) && dp[i+1][j-1]。
- 如果
完整代码:
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
char[] cs = s.toCharArray();
String res = new String();
boolean[][] dp = new boolean[n][n];
for (int i = 0; i < n; i++) {
dp[i][i] = true;
if (res.isEmpty()) res = s.substring(i, i + 1);
}
for (int i = n - 2; i >= 0; i--) {
for (int j = i + 1; j < n; j++) {
if (j - i == 1) {
dp[i][j] = cs[i] == cs[j];
}
else {
dp[i][j] = (cs[i] == cs[j]) && dp[i + 1][j - 1];
}
if (dp[i][j]) {
if (j - i + 1 > res.length()) res = s.substring(i, j + 1);
}
}
}
return res;
}
}
中心扩散
从每一个 奇数长/偶数长的 回文子串 中心点/长度为2的子串 出发,找到完整的回文子串比对。
完整代码:
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
char[] cs = s.toCharArray();
String res = s.substring(0, 1);
for (int i = 0; i < n - 1; i++) {
int[] odd = centerSpread(cs, i, i);
int[] even = centerSpread(cs, i, i + 1);
int[] max = odd[0] < even[0] ? odd : even;
if (max[1] - max[0] + 1 > res.length()) {
res = s.substring(max[0], max[1] + 1);
}
}
return res;
}
int[] centerSpread(char[] cs, int l, int r) {
while (l >= 0 && r < cs.length) {
if (cs[l] == cs[r]) {
l--; r++;
}
else {
break;
}
}
l++; r--;
return new int[]{l, r};
}
}