有三种解法:
(1)动态规划
(2)中心扩散
基本思想都是数学归纳法,解法见官网
(3)Manacher
我们重点讲一下第三种算法:
定理:任意回文子串,只需在首尾及其两个相邻的字符之间加入#,这个回文字符串的长度一定是奇数;且任意回文子串都是单中心的。
举例:
aba ——> #a#b#a# 长度为7的新回文串 回文中心为P[3][3]
abba ——> #a#b#b#a# 长度为9的新回文串 回文中心为P[4][4]
ManacherString:经过Manacher预处理的字符串,以下的概念都是基于ManasherString产生的。
回文半径和回文直径:因为处理后回文字符串的长度一定是奇数,所以回文半径是包括回文中心在内的回文子串的一半的长度,回文直径则是回文半径的2倍减1。比如对于字符串 "aba",在字符 'b' 处的回文半径就是2,回文直径就是3。
最右回文边界R:在遍历字符串时,每个字符遍历出的最长回文子串都会有个右边界,而R则是所有已知右边界中最靠右的位置,也就是说R的值是只增不减的。
回文中心C:取得当前R的第一次更新时的回文中心。由此可见R和C时伴生的。
半径数组:这个数组记录了原字符串中每一个字符对应的最长回文半径。
- 从i=0 开始采用中心扩散法进行扩散,记下C和R;
- 当遇到i < R 时,找出i关于C的对称点i'。
结论1:由于i 和 i' 关于C镜像对称,所以i和i'在(L,R) 范围内的可扩展性一致。而i'已经在前面计算过了。由此我们根据三种情况分析
(1)i' 的的回文半径没有超出L, 根据结论1那么i 的回文直径就等于i'的回文直径。
(2)i' 的回文半径超出了L,假设i的回文半径可以超出R,由于y=k恒成立,则必然有x=z那么证明C是可以继续扩展的,但是实际上C是不可以扩展的,由此证明i的回文半径就是i'到L, 也就是i到R。
(3)i' 的回文半径刚好到L,此时i的回文半径至少到R,可以从R继续向外延伸