题目描述
lc练习
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
实现
参考,还可以看官方讲解
- 第 1 步:定义状态
dp[i][j] 表示子串 s[i…j] 是否为回文子串,这里子串 s[i…j]定义为左闭右闭区间,可以取到 s[i] 和 s[j]。 - 第 2 步:思考状态转移方程
dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]
– 边界条件是:表达式 [i + 1, j - 1] 不构成区间,即长度严格小于 2,即 j - 1 - (i + 1) + 1 < 2 ,整理得 j - i < 3。
– 这个结论很显然:j - i < 3 等价于 j - i + 1 < 4,即当子串 s[i…j] 的长度等于 2 或者等于 3 的时候,其实只需要判断一下头尾两个字符是否相等就可以直接下结论了 - 第 3 步:考虑初始化
初始化的时候,单个字符一定是回文串,因此把对角线先初始化为 true,即 dp[i][i] = true 。
斜对角为true,然后填充右上半边
public class Solution {
public String longestPalindrome(String s) {
// 特判
int len = s.length();
if (len < 2) {
return s;
}
int maxLen = 1;
int index = 0;
// dp[i][j] 表示 s[i, j] 是否是回文串
boolean[][] dp = new boolean[len][len];
char[] chars = s.toCharArray();
for (int i = 0; i < len; i++) {
dp[i][i] = true;
}
for (int j = 1; j < len; j++) { //一列一列填充
for (int i = 0; i < j; i++) { // 只计算右上
if (chars[i] != chars[j]) {
dp[i][j] = false;
} else {
if (j - i < 3) {
dp[i][j] = true; //考虑边界
} else {
// (s[i] == s[j]) and dp[i + 1][j - 1]
dp[i][j] = dp[i + 1][j - 1];
}
}
// 只要 dp[i][j] == true 成立,就表示子串 s[i..j] 是回文,此时记录回文长度和起始位置
if (dp[i][j] && j - i + 1 > maxLen) {
maxLen = j - i + 1;
index = i;
}
}
}
return s.substring(index, index + maxLen);
}
}