马拉车(Manacher)算法(具体算法流程看这个哥们的:https://blog.csdn.net/qq_35065720/article/details/104205920):
算法解决:在一个字符串中找到最长的回文字符串。
实现策略:
以每个位置作为中心,向两边扩展,可以确定奇回文,但是偶回文无法这样做。
解决方法:在字符串中间及两边插入某种字符,此时可以按照这种方法进行扩展。此时无论奇回文还是偶回文都可以找到。
例如11211,此时添加任意字符在两边#1#1#2#1#1#此时均可以进行回文判断。
C++代码实现:
class Solution1 {
public:
char* manacherString(string str) {
char* charArr = new char[str.size() * 2 + 1];
int str_len = str.size();
for (int i = 1; i <= str_len; i++) {
charArr[2 * i] = str[i - 1];
charArr[2 * i + 1] = '#';
}
return charArr;
}
int maxLcpsLength(string str) {
if (str.size() == 0) {
return 0;
}
char* charArr = manacherString(str);
vector<int> pArr(strlen(charArr)); // 回文半径数组
int C = -1;
int R = -1;
int max_val = INT_MIN;
for (int i = 0; i != strlen(charArr); i++) {
pArr[i] = R > i ? min(pArr[2 * C - i], R - i) : 1;
// R > i 表示 i在回文右边界里面,有一个不用验的区域
// 2*C-i 为 i关于C的对称点i',两个瓶颈:1.i'的回文半径 2. R到我(i)的距离
while (i + pArr[i] < strlen(charArr) && i - pArr[i] > -1) { // 左右两边都不越界
if (charArr[i + pArr[i]] == charArr[i - pArr[i]]) { // 在不用验的区域下再扩一下
pArr[i]++;
}
else {
break;
}
}
if (i + pArr[i] > R) {
R = i + pArr[i]; // 更新右边界
C = i; // 更新中心位置
}
max_val = max(max_val, pArr[i]); // 全局最大值
}
return max_val - 1;
}
};