Manacher 字符串算法总结
Manacher 字符串算法总结
Manacher 算法,中文翻译俗称马拉车算法,其在字符串算法中并没有哈希和 KMP 那么有用处,不过在处理有关于回文串的问题时候则是非常快捷的线性字符串求出最大回文字串算法。
算法原理实现
Manacher 算法的题目背景是这样的,给定一个字符串
很明显可以想到一个思路,我们分别对
但是 Manacher 算法和哈希加上二分不同,它的时间更加快速,是一个线性算法,它同样也采用了中间断点的思路,不过在进行算法流程之前还需要做一步预处理操作:在字符串的每一个相邻字符直接插上 '#' 号,以及在最后添上 '@' 和在开头添上 '^',(其实这几个字符是什么都无所谓)。
之所以需要做预处理操作,是因为偶数和奇数的回文串不好一起考虑,需要进行分类讨论,但是经过我们的预处理,就可以只对奇数的回文串进行处理了,因为在其间添加了一些字符。
然后呢,我们需要维护一些变量来便于我们进行算法的流程,比如
然后,我们每次进行处理第
所以得出
但是如果
模板代码:
#include <iostream>
#include <cstdio>
#include <string>
const int N = 3e7 + 5;
std::string s, str;
int n, len, ans, r, mid, p[N];
void extend_str() {
str = '^';
for (int i = 0; i < s.size(); i++) {
str += '#';
str += s[i];
}
str += '#', str += '@';
len = s.size() * 2 + 1;
}
void manacher() {
for (int i = 1; i <= len; i++) {
p[i] = 1;
if (i < r) {
p[i] = std::min(p[mid * 2 - i], r - i);
}
while (str[i + p[i]] == str[i - p[i]]) p[i]++;
if (i + p[i] > r) {
mid = i;
r = i + p[i];
}
ans = std::max(ans, p[i] - 1);
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> s;
extend_str();
manacher();
std::cout << ans << '\n';
}