题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2342
题意:求最长子串使得它有四个相同的回文串SSSS相连组成。
首先跑一边Manacher,初始化出以每一个点为最长回文串的左端点,然后按左端点排序。
枚举中间点$x$,然后找右面的中间点$y$,使得$y$满足
$y-p_yleq x$
$yleq x+r_xdiv 2$
用set维护y,然后求出最接近$x+r_xdiv 2$,用--upper_bound()返回$y$的迭代器it。(注意不要直接用lower_bound()
则$ans=max((*it)-i) imes 2$ -->因为有‘#’,*2即可。
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<set> 6 using namespace std; 7 const int N=500050; 8 int p[N*2]; 9 char str[N],s[N*2]; 10 int n,t,ans; 11 set<int> Set; 12 set<int>::iterator it; 13 14 struct node{ 15 int v,id; 16 }a[N]; 17 18 bool cmp(node x,node y){ 19 return x.v<y.v; 20 } 21 22 void manacher(int len){ 23 s[0]='$'; s[++t]='#'; 24 for(int i=1;i<=len;i++){ 25 s[++t]=str[i]; 26 s[++t]='#'; 27 } 28 int pos=0,mx=0; 29 for(int i=1;i<=t;i++){ 30 if(i>mx) p[i]=1; 31 else p[i]=min(p[2*pos-i],mx-i); 32 while(i+p[i]<=t&&i-p[i]>=1&&s[i+p[i]]==s[i-p[i]]) p[i]++; 33 if(i+p[i]>mx){ 34 mx=i+p[i]; 35 pos=i; 36 } 37 } 38 } 39 40 void solve(){ 41 int q=0; 42 for(int i=1;i<=t;i++) if(i&1) a[++q].v=i-p[i],a[q].id=i; 43 sort(a+1,a+q+1,cmp); 44 int now=1; 45 for(int i=1;i<=t;i++) if(i&1){ 46 while(now<q&&a[now].v<=i) Set.insert(a[now].id),now++; 47 it=--Set.upper_bound(i+p[i]/2); 48 if(it!=Set.begin()) ans=max(ans,(*it)-i); 49 } 50 printf("%d ",ans*2); 51 } 52 53 int main(){ 54 scanf("%d",&n); 55 scanf("%s",str+1); 56 manacher(n); 57 solve(); 58 return 0; 59 }