HDU 5371 Hotaru的问题

题意:
Hotaru Ichijou最近沉迷于数学问题。现在她正在玩N序列。
让我们定义N序列,它由三部分组成并满足以下条件:
1.第一部分与第三部分相同
2.第一部分和第二部分是对称的
例如,序列{2,3,4,4,3,2,2,3,4}是N序列,其中第一部分{2,3,4}与第三部分{2,3,4}相同,第一部分{2,3,4}和第二部分{4,3,2}是对称的。
给你n个正整数,你的任务是找到最大的连续子序列,即N序列。
题解:
①首先,肯定要用Manacher求出回文半径
②定义L[i]:以i为回文中心的最长回文串的最左端点
定义R[i]:以i为回文中心的最长回文串的最右端点
③将问题转化一下,我们发现,其实它就是让求回文中心(i,j),满足:
L[i]<=j<i<=R[j]
④可以用并查集维护
⑤初始时 prt[j] = j,
⑥可以发现如果j对i不可行(R[j]<i),那么对i+1也一定不可行,此时令prt[j] = prt[j+1]
⑦对于i,从 j = prt[L[i]]开始跳,注意路径压缩
⑧最后的答案为ans*3,是因为在过程中我们只维护了第二部分也就是i~j的长度

#pragma GCC optimize (2)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=200000+10;
int n,len,s[maxn],L[maxn],R[maxn],P[maxn];
int f[maxn];
int Find(int x){
        if(f[x]==x)return x;
        return f[x]=Find(f[x]);
}
void Init();
void Manacher();
signed main(){
        int t;scanf("%d",&t);
        for(int i=1;i<=t;i++){
                printf("Case #%d: ",i);
                Init();
        }
        return 0;
}
void Init(){
        scanf("%d",&len);
        for(int i=1;i<=len;i++)scanf("%d",&s[i]);
        Manacher();
        for(int i=1;i<=n;i++)f[i]=i;
        int ans=0,tmp=0;
        for(int i=1;i<=n;i+=2){
                int j=Find(L[i]);
                while(j<i && j>0){
                        if(i<=R[j]){
                                tmp=(i-j+1)>>1;
                                ans=max(ans,tmp);
                                break;
                        }
                        else if(i>R[j])f[j]=Find(j+2);
                        j=Find(j+2);
                }
        }
        printf("%d
",ans*3);
        //最后的答案为ans*3,是因为在过程中我们只维护了第二部分也就是i~j的长度
}
void Manacher(){
        memset(P,0,sizeof(P));
        n=len<<1|1;
        for(int i=n;i>=1;i--)
                if(i&1)s[i]=-1;
                else s[i]=s[i>>1];
        s[0]=-2;
        int id=0,mx=0;
        for(int i=1;i<=n;i++){
                if(i<mx)P[i]=min(P[id*2-i],mx-i);
                else P[i]=1;
                while(s[i+P[i]]==s[i-P[i]])P[i]++;
                if(i+P[i]>mx)mx=i+P[i],id=i;
                L[i]=i-P[i]+1;
                R[i]=i+P[i]-1;
        }
}

 

原文地址:https://www.cnblogs.com/holy-unicorn/p/9510605.html