/**
* i: 当前位置
* i': i关于C的对称点
* L: 回文最左边界
* R: 回文最右边界
* C: 回文中心
* max: 回文最大半径
* maxC: 当达到最大半径时的中心
*
* 分情况:
* i 在 R 外: 直接暴力往外扩
* i 在 R 内:
* 1. parr[i] 在 [L,R] 内, parr[i] = parr[i']
* 2. parr[i] 超出了 [L,R]的范围, 从R 开始往外扩
* 3. parr[i] 刚好就是[L,R], parr[i] = R - i
*
* 所以最小不用往外扩的范围就是,一个字符它本身一定是回文的
* R > i ? Math.min((R - i), parr[C - (i - C)]) : 1
*/
public class Leetcode_0005_LongestPalindromicSubstring {
public static String longestPalindrome(String str) {
if (str == null || str.length() == 0) {
return ""
}
char[] charArr = str2ManacherStr(str)
// 回文半径数组
int[] pArr = new int[charArr.length]
// 回文最右边界的下一个位置 [L,R)
int R = -1;
// 回文中心
int C = -1;
// 回文最大半径
int max = -1;
// 最大半径的中心
int maxC = -1;
for (int i = 0; i < charArr.length; i++) {
// 找到最小不用往外扩的位置
pArr[i] = R > i ? Math.min(pArr[2 * C - i], R - i) : 1
// 暴力扩
while (i + pArr[i] < charArr.length && i - pArr[i] >= 0) {
if (charArr[i + pArr[i]] == charArr[i - pArr[i]]) {
pArr[i]++
} else {
// 第一没找到就匹配失败
break
}
}
// 更新R C
if (i + pArr[i] > R) {
R = i + pArr[i]
C = i
}
// 更新max maxC
if (pArr[i] > max) {
max = pArr[i]
maxC = i
}
}
StringBuilder builder = new StringBuilder()
for (int i = maxC - max + 1
builder.append((i & 1) == 0 ? "" : charArr[i])
}
return builder.toString()
}
private static char[] str2ManacherStr(String str) {
char[] manStr = new char[str.length() * 2 + 1]
int index = 0
for (int i = 0
manStr[i] = (i & 1) == 0 ? '
}
return manStr
}
}