算法1. 中心延拓 但是要考虑及奇延拓和偶延拓 eg: abba abcba
算法2. 马拉车:
首先进行预处理 保证长度是奇数 只考虑奇延拓 同时在边界插入哨兵
数组p[i] 表示处理后的数组的最大延拓个数(考虑#时p[i]+i得到延拓到的右边界)
p[6]=5, p[6]+6=11, cbcbc恰好就是以c为中心的最长回文串长度。故最后返回p[]的最大值即可。
上图
当p[c]+c>i 时, 采用如下方法, 否则采用中心延拓
string manacher(string s){
string str = "@#";
for(char &c : s){
str.push_back(c);
str.push_back('#');
}
cout<<str<<endl;
// 记录最远点和最远点对应的中心点
int len=str.length(), right=0, mid=0;
// 最大回文串对应的中心位置和长度
int maxlen=0, maxmid=0;
vector<int> p(len, 0);
for(int i=1;i<len;i++){
// 先对p[i]赋一个尽可能大的值 在进行延拓判断 从第一个非哨兵元素开始
p[i] = right>i ? min(p[2*mid-i], right-i) : 1;
while(str[p[i]+i]==str[i-p[i]]) p[i]++;
// 更新右边界
if(p[i]+i>right){
right = p[i]+i;
mid = i;
}
if(p[i]>maxlen){
maxlen = p[i];
maxmid = i;
}
}
// 注意: maxmid 是处理后的中心 原中心为maxmid-1
return s.substr(maxmid/2-maxlen/2, maxlen-1);
}