求最长回文串的利器 - Manacher算法
Manacher主要是用来求某个字符串的最长回文子串.
不要被manacher这个名字吓倒了,其实manacher算法很简单,也很容易理解,程序短,时间复杂度为O(n).
求最长回文子串这个问题,我听说有个分治+拓展kmp的算法,后缀数组也可以.
但是对于求回文串来说,manacher算法肯定有很多其他算法没有的优点。
现在进入正题:首先,在字符串s中,用rad[i]表示第i个字符的回文半径,即rad[i]尽可能大,且满足:
s[i-rad[i],i-1]=s[i+1,i+rad[i]]
很明显,求出了所有的rad,就求出了所有的长度为奇数的回文子串.
至于偶数的怎么求,最后再讲.
假设现在求出了rad[1..i-1],现在要求后面的rad值,并且通过前面的操作,得知了当前字符i的rad值至少为j.
现在通过试图扩大j来扫描,求出了rad[i].再假设现在有个指针k,从1循环到rad[i],试图通过某些手段来求出[i+1,i+rad[i]]的rad值.
根据定义,黑色的部分是一个回文子串,两段红色的区间全等.
因为之前已经求出了rad[i-k],所以直接用它.有3种情况:
![](https://images0.cnblogs.com/blog2015/606573/201508/191556387694104.jpg)
那橙色以外的部分就不是了吗?这是肯定的.因为如果橙色以外的部分也是回文的,那么根据青色和红色部分的关系,可以证明黑色部分再往外延伸一点也是一个回文子串,这肯定不可能,因此rad[i+k]=rad[i]-k.为了方便下文,这里的rad[i+k]=rad[i]-k=min(rad[i]-k,rad[i-k]).
②rad[i]-k>rad[i-k]
![](https://images0.cnblogs.com/blog2015/606573/201508/191557315351457.jpg)
模板题:HDU 3068