manacher
简介
求出字符串的所有回文子串。
算法思想和流程
我们想找到每一个字符 \(i\) 作为回文中心的时候,最长回文串的半径 \(r_i\) 是什么。那么以 \(i\) 为中心,\([0, r_i]\) 为半径,都是回文子串,\((r_i, +\inf)\) 为半径,都不是。考虑暴力算法对于每一个中心向外探测,时间复杂度 \(O(n^2)\)。
考虑之前的信息对求解问题的作用。在 KMP 算法中,我们额外维护了一个跳转指针,使得复杂度在优化下产生了质变。在 manacher 算法中,利用之前求出的回文串,考虑目前这个字符在之前回文串中的相反位置上的对应字符,这两个字符在回文串内具有相似的性质,对其加以利用,使得探测的字符个数大幅度变少。
维护一个指针 \(r\),表示之前所探测到的回文串的最右边端点是什么。对于目前回文中心 \(i\):
- 如果 \(i > r\),那么从 \(i\) 开始探测。
- 否则找到 \(i\) 的对应点,找到其为中心的最长回文子串,和大回文串边界求 \(\max\),这个点要么 \(=r\),要么探测一步就会不匹配。从这个点往外探测。
容易发现一次探测使得 \(r\) 前进 \(1\) 步以上,因此时间复杂度 \(O(n)\)。