题解 P3805 【【模板】manacher算法】
重拾
首先,考虑到回文串分奇数和偶数两种情况,需要分类讨论,所以我们可以考虑在所有字符之间插入一个没有用过的符号'#'
然后边界问题不好处理,所以可以在字符串的开头加上一些奇怪的符号'~'
接下来就是
我们定义
发现我们可以
在定义
然后发现,对于每一个
Case1: mid<i<mr
由于
但是当
Case2:i<mr
这个时候我们不能求出i的对称点,直接暴力拓展即可
由于
Code:
#include<bits/stdc++.h>
using namespace std;
#define rep(i, s, t) for(int i = s; i <= t; ++ i)
#define maxn 22000005
int n, m, cnt, p[maxn], mid, mr, Ans;
char c[maxn], s[maxn];
void build() {
scanf("%s", c + 1), n = strlen(c + 1), s[++ cnt] = '~', s[++ cnt] = '#';
rep(i, 1, n) s[++ cnt] = c[i], s[++ cnt] = '#';
s[++ cnt] = '!';
}
void solve() {
rep(i, 2, cnt - 1) {
if(i <= mr) p[i] = min(p[mid * 2 - i], mr - i + 1);
else p[i] = 1;
while(s[i - p[i]] == s[i + p[i]]) ++ p[i];
if(i + p[i] > mr) mr = i + p[i] - 1, mid = i;
Ans = max(Ans, p[i]);
}
printf("%d", Ans - 1);
}
int main() { return build(), solve(), 0; }