【BZOJ】【2565】最长双回文串

时间:2023-11-13 08:25:38

Manacher算法


  找出一个最长子串S=X+Y,且X和Y都是回文串,求最长的长度是多少……

  同时找两个串明显很难搞啊……但是我们可以先找到所有的回文串!在找回文串的同时我们可以预处理出来l[i]和r[i]分别表示从 i 这个位置开始向左/右最长的回文串有多长,那么我们枚举两个回文串的分割点更新答案即可。

 /**************************************************************
Problem: 2565
User: Tunix
Language: C++
Result: Accepted
Time:80 ms
Memory:4496 kb
****************************************************************/ //BZOJ 2565
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
using namespace std;
typedef long long LL;
inline int getint(){
int r=,v=; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-;
for(; isdigit(ch);ch=getchar()) v=v*+ch-'';
return r*v;
}
const int N=1e5+,INF=~0u>>;
/*******************template********************/
char s[N];
int p[N<<],a[N<<],l[N<<],r[N<<],n;
int main(){
scanf("%s",s);
n=strlen(s);
F(i,,n) a[i<<]=s[i-];
n=n<<|; int id=,mx=;
F(i,,n){
if (mx>i) p[i]=min(p[*id-i],mx-i);
while(i-p[i]-> && i+p[i]+<=n && a[i-p[i]-]==a[i+p[i]+]){
p[i]++;
l[i+p[i]]=max(l[i+p[i]],p[i]);
r[i-p[i]]=max(r[i-p[i]],p[i]);
}
if (p[i]+i>mx) mx=p[i]+i,id=i;
l[i+p[i]]=max(l[i+p[i]],p[i]);
r[i-p[i]]=max(r[i-p[i]],p[i]);
}
/*
F(i,1,n) printf("%c ",a[i]!=0?a[i]:'#'); puts("");
F(i,1,n) printf("%d ",p[i]); puts("");
F(i,1,n) printf("%d ",l[i]); puts("");
F(i,1,n) printf("%d ",r[i]); puts("");
*/
int ans=;
F(i,,n) if(l[i]+r[i]>ans) ans=l[i]+r[i];
printf("%d\n",ans);
return ;
}