最长回文子串
如果给你一个字符串abcbcbd,这个字符串里所包含的最长的回文子串是什么呢?毫无疑问,是bcbcb,它的长为6,
我们给出一个暴力简洁的算法:遍历整个字符串,对于每一个字符,都向左和右边找相等的字符,每次更新最大值,直到遍历完成。这样的算法看似简单,但是会遇到一个问题:对于奇数长度的回文串好处理,但对于偶数长度的回文串就比较麻烦。同时,这种算法的最坏复杂度为n^2,我们需要更加高效的算法。于是,“马拉车算法”,也就是Manacher算法就诞生了。
Manacher算法
在计算机科学中,最长回文子串或最长对称因子问题是在一个字符串中查找一个最长的连续的回文的子串,例如“banana”最长回文子串是“anana”。最长回文子串并不一定是唯一的,比如“abracadabra”,没有超过3的回文子串,但是有两个回文字串长度都是3:“ada”和“aca”。在一些应用中,我们求出全部的极大回文子串(不被其他回文串包含的回文子串)。
Manacher发现了一种线性时间算法,可以在列出给定字符串中从任意位置开始的所有回文子串。并且,Apostolico, Breslauer & Galil发现,同样的算法也可以在任意位置查找全部极大回文子串,并且时间复杂度是线性的。因此,他们提供了一种时间复杂度为线性的最长回文子串解法。另外,Jeuring (1994)[3], Gusfield (1997)发现了基于后缀树的算法。也存在已知的高效并行算法。
Manacher算法的算法原理,是在每两个字符之间,都插入#号,这样每个字符串都会变成奇数长度的字符串,同时,要在首位插入无关字符$,防止#和开头的#配对
abcbcbd
$#a#b#c#b#c#b#d#
对于每一个字符i,我们先判断它是否已经被包括在前面已经计算能包括住i的整个最长回文串里面,如果在里面,那么以它关于前一个最长回文串的中点id对称的点j为中心的最长回文长度应该已经计算出来了,如果以那个j为中心的的最长回文串已经包括在在计算好的最长回文串里面,那么我们有p[id-(i-id)]=p[i] 也就是p[j]=p[i]这段话看起来很拗口,但这也是manacher算法的重点