Hotaru's problem HDU - 5371

http://acm.hdu.edu.cn/showproblem.php?pid=5371

直接暴力也可以过 不理解 还是线段树优化

对每个偶数回文中心 求出回文半径 只要两个回文中心互相在对方回文半径范围之内 那就是一个题目要求的串

然后用 回文中心+回文半径=最远到达距离 建立线段树 然后从左到右扫一遍 对每个位置 看自己左边回文半径内能覆盖自己的最远即最小的回文中心位置 找到后作差即为所求

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;

int maxx[4*maxn];
int ary[2*maxn],book[2*maxn];
int n;

void manacher(int *ary,int n)
{
    int i,p,r;
    p=0,r=0;
    for(i=0;i<n;i++)
    {
        if(i<r) book[i]=min(book[2*p-i],r-i);
        else book[i]=1;
        while(0<=i-book[i]&&i+book[i]<n&&ary[i-book[i]]==ary[i+book[i]]) book[i]++;
        if(r<=i+book[i]) p=i,r=i+book[i];
    }
}

void build(int l,int r,int cur)
{
    int m;
    if(l==r)
    {
        maxx[cur]=l+book[l];
        return;
    }
    m=(l+r)/2;
    build(l,m,2*cur);
    build(m+1,r,2*cur+1);
    maxx[cur]=max(maxx[2*cur],maxx[2*cur+1]);
}

void query(int pl,int pr,int pos,int &res,int l,int r,int cur)
{
    int m;
    //printf("*%d %d %d %d %d %d*\n",pl,pr,pos,l,r,maxx[cur]);
    if(pl<=l&&r<=pr)
    {
        if(maxx[cur]<pos) return;
        if(l==r)
        {
            //printf("*%d %d %d %d %d*\n",pl,pr,l,r,maxx[cur]);
            res=l;
        }
        else
        {
            m=(l+r)/2;
            if(res==-1) query(pl,pr,pos,res,l,m,2*cur);
            if(res==-1) query(pl,pr,pos,res,m+1,r,2*cur+1);
        }
        return;
    }
    m=(l+r)/2;
    if(res==-1&&pl<=m) query(pl,pr,pos,res,l,m,2*cur);
    if(res==-1&&pr>m) query(pl,pr,pos,res,m+1,r,2*cur+1);
}

void show(int l,int r,int cur)
{
    int m;
    //printf("*%d %d %d*\n",l,r,maxx[cur]);
    if(l==r) return;
    m=(l+r)/2;
    show(l,m,2*cur);
    show(m+1,r,2*cur+1);
}

int main()
{
    int t,cas,i,res,ans;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            ary[2*i]=-1;
            scanf("%d",&ary[2*i+1]);
        }
        ary[2*n]=-1;
        manacher(ary,2*n+1);
        for(i=0;i<n-1;i++) book[i]=(book[2*(i+1)]-1)/2;
        if(n-2>=0) build(0,n-2,1);

        //for(i=0;i<n-1;i++) printf("%d ",book[i]);
        //printf("\n");
        //show(0,n-2,1);

        ans=0;
        for(i=0;i<n-1;i++)
        {
            res=-1;
            if(0<=i-book[i]&&i-book[i]<=i-1) query(i-book[i],i-1,i,res,0,n-2,1);
            if(res!=-1)
            {
                //printf("*%d*\n",res);
                ans=max(ans,i-res);
            }
        }

        printf("Case #%d: %d\n",cas,3*ans);
    }
    return 0;
}

/*
100
10
2 2 3 4 4 3 2 2 3 4

10
2 3 4 4 3 2 2 3 4 4

6
1 1 1 1 1 1
*/

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/82977427