一、Manacher 算法
时间复杂度
线性时间内求解最长回文子串的算法
思路:
1.预处理,将相邻字符中间插入 \#,把字符串变为s,使得所有字符串变成奇数长度
2.f(i) 来表示以 s 的第 i 位为回文中心,f(i)−1 就是以 ii 为中心的最大回文串长度
3.枚举计算
[1,i−1] 区间内所有点的 f(i),
[1,i−1] 这些点作为回文中心时候的最大半径
[1, i - 1][1,i−1] 拓展出的回文达到最大半径时的回文右端点
4.维护信息
当前最大的回文的右端点 r_m
这个回文右端点对应的回文中心 i_m
算法:
- 初始化 f(i)
1. i <= r_m :i 被包含在当前最大回文子串内
假设 j 是 i 关于 r_m 的对称的位置
那么f(i) = min(f(j) ,r_m-i+1)
2. i > r_m :f(i)=1
- 中心拓展
1.初始化后 s[i+f(i)−1]=s[i−f(i)+1]
2. 判断 s[i + f(i)]和s[i−f(i)] 是否相等
3. 如果相等将 f(i 自增;
4. 这样循环直到 s[i + f(i)] != s[i - f(i)]
- 越界处理
1. 开头加一个 $,并在结尾加一个 !
2. 开头和结尾的两个字符一定不相等,循环就可以在这里终止
二、中心拓展
时间复杂度
枚举回文中心的是 O(n) ,每个回文中心拓展的次数也是 O(n)
时间复杂度是 O(n^2)
思路
1.枚举每一个可能的回文中心
2.两个指针分别向左右两边拓展
3.两个指针指向的元素相同的时候就拓展
4.直到不相等停止拓展
奇偶数回文串
1.奇数,那么回文中心是一个字符
2.偶数,那么中心是两个字符
优化思路
1.长度n 的字符串会生成 2n-12n−1 组回文中心
2.Li = i/2 ,Ri = Li + i mod 2