Manacher算法详解与应用
时间复杂度O(n)
概念
<1>回文半径数组
<2>最右回文半径
可能性:
<1>i在R外 暴力
<2>i在R内
(1)i回文在L,R内 O(1)
(2)i回文在L,R外 O(1)
(3)i回文左边界与L压线,从R右边界扩
(1) t[f(aBa)kTk(aBa)f]s
(2) (ab[cEcba)tTtab(cEc)]f
(3) [(abcEcba)fFf(abcEcba)]s
[]对应L,R ()对应i的回文
#include<bits/stdc++.h>
using namespace std;
char *manacherString(string s){
char *res = new char[s.length() * 2 + 1];
int index = 0;
for (int i = 0; i < s.length() * 2 + 1;i++)
res[i] = (i & 1) ? s[index++] : '#';
return res;
}
int manacher(string s){
if (s.length() == 0)
return 0;
char *charArr = manacherString(s);
int charArrLen = s.length() * 2 + 1;
int *pArr = new int[charArrLen];
int C = -1, R = -1; //C为中心 R右为边界
int Max = INT_MIN;
for (int i = 0; i < charArrLen ; i++){
pArr[i] = R > i ? min(pArr[2 * C - i] , R-i) : 1; //2、3种情况 1、4(边界)种情况
while (i + pArr[i] < charArrLen && 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 = max(Max , pArr[i]);
}
return Max - 1;//因增加#原因
}
int main(){
string s;
cin>>s;
cout<<manacher(s)<<endl;
}