Manacher 算法 1
\(Manacher\) 回文串利器当然不排除\(PAM\)这种玩意
压倒式的简单&\(O(n)\)的时间复杂度使得它胜出了
这玩意是求出以一个点为中心的最长回文串
拿一个已经知道的点去扩展右边界
记当前更新的点为\(i\),选点为\(now\),\(now\)为中心时最长回文串左右端点为\(l,r\)
对于\(i\)来说,关于\(now\)对称的点\(j\)的最长串已经更新完毕,记左右端点为\(jl,jr\)
这个时候由于\([l,r]\)之间是回文的,所以我们就知道\([i-(j-jl),i+(jr-j)]\)可能是一个回文串(需要更充分的条件)
但是我们知道\([l,j+(j-l)]\)是回文的,所以\([i-(j-l),i+(j-l)]\)是回文的
别的部分暴力\(check\)就好了
这一部分结束以后,当前答案由于中间插空答案会大\(1\)
然后再去一直更新就好了
由于回文串的性质,实际上求出了最长回文串就相当于求出了所有回文串,只不过是次级信息
对于奇偶回文串的处理就是中间插空直接搞
最后就是答案减1;
Code:
点击查看代码
void Manacher(){
int m=2,len=strlen(ch+1);
a[1]='$',a[2]='&';
for(int i=1;i<+n;i++){
m++;
a[m]=ch[i];
m++;
a[m]='&';
}
for(int i=3,now=0,r=0;i<m;i++){
if(i<r){
q[i]=min(q[mid*2-i],r-i);
}
else{
q[i]=1;
}
while(a[i-q[i]]==a[i+q[i]]){
q[i]++;
}
if(i+q[i]>r){
r=q[i]+i;
mid=i;
}
}
}
两个校测的例题不方便放就扔文章题解区了