manacher 算法
manacher 算法
作用
在\(O(n)\)的时间里求出以每个字符或者两个相邻字符之间为回文重心的回文串半径
算法流程
对于一个字符串\(S=abbacabba\)
我们不妨在两个在字符中间加入一个不可能存在在字符串中的字符,在两边加入一些奇怪的字符,S`=!a#b#b#a#c#a#a#b#b#a@
这个操作十分的风骚,这样可以将以上两种情况合并在一起。
不妨定义数组\(p[i]\) 为以\(i\)为中心最长回文串的半径。
不妨定义mx
为目前找到的回文串的最右端。
不妨定义mid
为目前最右回文串的回文中心
易得\(p[1]=1\)
我们假设我们已经将\(p[1,i-1]\) 求出,将要计算\(p[i]\) 我们该怎么办?
所以我们可以先得到\(p[i]=\min(mx-i,p[mid*2-i])\)
当然有个前提\(i<=mx\)
但是其还有可能想外扩张,所以还要再加上一句(这个好似木有前提,就是个暴力):
while(S[i-p[i]]==s[i+p[i]]) p[i]++;
然后还要再更新一下\(mx,mid\)
大体就是这样,那先放一下代码。
CODE
char a[maxn];
int mx,mid,p[maxn];
inline void manacher(){
for(int i=1;i<=la;i++){
if(i<=mx) p[i]=min(mx-i,p[mid*2-i]);
while(a[i+p[i]]==a[i-p[i]]) p[i]++;
if(p[i]+i-1>=mx) mx=p[i]+i-1,mid=i;
}
}