题解 | #最长回文子串#
最长回文子串
https://www.nowcoder.com/practice/b4525d1d84934cf280439aeecc36f4af
/**
* ☆☆☆☆☆
* 最长回文子串
* 中心扩展 + 动态规划 + Manacher
*/
private static void longestPalindrome() {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String s = in.nextLine();
// 字符间隔及两边插入#,方便统一中心扩展方式的两种情况:中心在元素上和中心在元素间
StringBuilder sb = new StringBuilder("#");
for (int i = 0; i < s.length(); i++) {
sb.append(s.charAt(i)).append("#");
}
// 数组用于存插入#后,当前元素为中心的最大回文半径(自身算1)
// 最终的最大回文长度是该半径-1(该半径多出来的#,比另一边的原字符多一)
int[] arr = new int[sb.length()];
// 已知的所有回文串的最右边界+1
int maxPos = 0;
// 边界最右的回文串的中心
int index = 0;
for (int i = 0; i < sb.length(); i++) {
if (i < maxPos) {
// 此处是关键,i相对index的对称位置2*index-i,直接参与计算,避免重复计算
arr[i] = Math.min(arr[2 * index - i], maxPos - i);
} else {
arr[i] = 1;
}
// 在已有基础上继续扩展判断,越界判断,以及两边字符判断
while (i - arr[i] >= 0 && i + arr[i] < sb.length() && sb.charAt(i - arr[i]) == sb.charAt(i + arr[i])) {
arr[i]++;
}
// 更新maxpos和index
if (i + arr[i] > maxPos) {
maxPos = i + arr[i];
index = i;
}
}
int max = 0;
for (int i = 0; i < sb.length(); i++) {
max = Math.max(max, arr[i]);
}
// 最长回文串的长度
System.out.println(max - 1);
// 最长回文串
for (int i = 0; i < sb.length(); i++) {
if (max == arr[i]) {
String result = sb.substring(i - arr[i] + 1, i + arr[i]).replace("#", "");
System.out.println(result);
break;
}
}
}
}
查看18道真题和解析