最长回文子串
题目
-
给你一个字符串
s,找到s中最长的 回文 子串。示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。示例 2:
输入:s = "cbbd" 输出:"bb"提示:
1 <= s.length <= 1000s仅由数字和英文字母组成
分析
- 预处理:将 "abc" 转换为 "#a#b#c#",这样奇偶长度回文都变成奇数长度
核心变量含义
int[] p = new int[t.length()]; // p[i] = 以位置i为中心的回文半径
int center = 0, right = 0; // center = 当前覆盖最远的回文中心
// right = 该回文能到达的最右边界
算法的三种情况
假设我们正在处理位置 i:
情况1:i 超出了已知范围
当 i >= right 时,无法利用之前信息,只能从头开始扩展
p[i] = 0,然后直接进入while循环扩展
情况2:i 在已知回文范围内
当 i < right 时,可以利用对称性:
left center i right
| | | |
...L........C.......i......R...
| | | |
mi
mi = 2 * center - i (i关于center的镜像位置)
if (i < right) {
p[i] = Math.min(right - i, p[mi]);
}
为什么用Math.min?
p[mi]:镜像位置的回文半径right - i:i到右边界的距离- 取最小值是因为i的回文不能超出已知的右边界
扩展阶段
while (i + p[i] + 1 < t.length() && i - p[i] - 1 >= 0
&& t.charAt(i + p[i] + 1) == t.charAt(i - p[i] - 1)) {
p[i]++;
}
无论哪种情况,都要尝试继续扩展:
i + p[i] + 1和i - p[i] - 1是下一对要比较的字符- 如果相等,回文半径+1
更新center和right
if (i + p[i] > right) {
right = i + p[i];
center = i;
}
如果以i为中心的回文超出了当前的right,就更新center和right,为后续位置提供更多信息。
举例说明
对于字符串 "babad" → "#b#a#b#a#d#":
位置: 0 1 2 3 4 5 6 7 8 9 10
字符: # b # a # b # a # d #
p值: 0 1 0 3 0 1 0 1 0 1 0
当处理位置4('#')时:
- center=3, right=6
- mi = 2*3-4 = 2
- p[4] = min(6-4, p[2]) = min(2, 0) = 0
- 然后扩展发现s[3]='a', s[5]='b'不等,所以p[4]=0
这样通过利用已知信息,避免了大量重复计算,实现O(n)时间复杂度。
code
public class Main {
public String longestPalindrome(String s) {
if (s.length() == 0 || s.length() == 1)
return s;
String t = processString(s);
int[] p = new int[t.length()];
int center = 0, right = 0;
int maxLen = 0, maxCenter = 0;
for (int i = 0; i < t.length(); i++) {
if (i < right)
p[i] = Math.min(right - i, p[2 * center - i]);
while (i + p[i] + 1 < t.length() && i - p[i] - 1 >= 0
&& t.charAt(i + p[i] + 1) == t.charAt(i - p[i] - 1))
p[i]++;
if (i + p[i] > right) {
right = i + p[i];
center = i;
}
if (p[i] > maxLen) {
maxLen = p[i];
maxCenter = i;
}
}
int st = (maxCenter - maxLen) / 2;
return s.substring(st, st + maxLen);
}
public String processString(String s) {
StringBuilder t = new StringBuilder();
t.append('#');
for (int i = 0; i < s.length(); i++) {
t.append(s.charAt(i)).append('#');
}
return t.toString();
}
}

浙公网安备 33010602011771号