题解:P3805 【模板】manacher
__xxy_free_ioi__ · · 题解
题解:P3805 【模板】manacher
真是有意思的算法捏,呵呵
解法
很容易能想到
首先,我们需要对数据做一个小小的改变,因为一个回文串的对称中心不一定是整数,所以我们要想办法将其变成整数。所以,我们可以把它的每两个字符中间加上一个相同的特殊字符(这里指原串中不会出现的字符),例如,
为了方便,我们设
我们发现,在
情况 1:i \le r
我们设
因为
综上,
情况 2:i > r
这种情况我们只能由
由此,我们就以
时间复杂度
让我们来看看它的时间复杂度为啥是
- 暴力扩展次数有限:
r 只能被扩展n 次。 - 非暴力扩展复杂度低:只有
O(1) 的复杂度。
所以,总的复杂度是
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1.1e7 + 5;
int n, res;
int rad[2 * N];
char s[2 * N], c;
void read() {
s[0] = 'B';
while (cin >> c) s[++n] = 'A', s[++n] = c;
s[++n] = 'A';
}
int main() {
read();
int mid = 0, r = 0;
for (int i = 1; i <= n; i++) {
int j = 2 * mid - i;
if (r < i) rad[i] = 1;
else rad[i] = min(rad[j], r - i + 1);
while (s[i - rad[i]] == s[i + rad[i]]) rad[i]++;
res = max(res, rad[i] - 1);
if (i + rad[i] - 1 > r) {
r = i + rad[i] - 1;
mid = i;
}
}
cout << res;
return 0;
}