【模板】最长回文串长度:manacher 算法
\(pa_i\) 表示以 \(i\) 为中心的(原串的)回文串长度
点击查看代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int n,m,pa[22000010];
char buf[11000010],a[22000010];
void manacher(char *a){
int len=strlen(a+1);
for(int i=1,mid=0,r=0;i<=len;i++){
if(i<=r) pa[i]=min(pa[mid*2-i],r-i);
while(a[i-pa[i]-1]==a[i+pa[i]+1]) pa[i]++;
if(i+pa[i]>r) r=i+pa[mid=i];
}
}
int main(){
// #ifdef LOCAL
// freopen("input.in","r",stdin);
// #endif
scanf("%s",buf+1),n=strlen(buf+1);
a[0]='~',a[m=1]='|';
for(int i=1;i<=n;i++) a[++m]=buf[i],a[++m]='|';
a[++m]=0;
printf("%d\n",manacher(a));
return 0;
}
注意这个处理,是 ~|a|a|a|a|a?
点击查看代码
#include <cstdio>
#include <cstring>
#include <vector>
#include <cassert>
#include <algorithm>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
typedef long long LL;
int n, pal[1 << 25];
char buf[1 << 25], a[1 << 25];
void manacher() {
for (int i = 1, mid = 0, r = 0; i <= n; i++) {
if (i <= r) pal[i] = min(pal[mid * 2 - i], r - i + 1);
while (a[i - pal[i]] == a[i + pal[i]]) ++pal[i];
if (i + pal[i] - 1 > r) r = i + pal[mid = i] - 1;
}
}
int main() {
scanf("%s", buf);
int len = strlen(buf);
a[0] = '~';
a[++n] = '|';
for (int i = 0; i < len; i++) a[++n] = buf[i], a[++n] = '|';
a[++n] = '?';
manacher();
printf("%d\n", *max_element(pal + 1, pal + n + 1) - 1);
return 0;
}
大致思路是,记当前右端点最右的回文串的右端点是 \(r\),中点是 \(mid\),那么如果 \(mid<i\leq r\),\(i\) 的回文串长度至少是它的对称,\(2mid-i\)。从这个半径开始暴力扩展。
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/template-manacher.html