【GDKOI2016】项链Code&Details

Details

首先,我们得出了结论,两个回文串相交才符合条件,在总结上已经说了。
然后假设当前这位枚举到一个回文串的中心i,那么再找另一个会问串中心满足两个条件:1、i-p[i]<=j+p[j](两个回文串相交);2、i-j<=n(两个回文串中心的距离不得超过原串的长度,否则可能不合法)
那么我们把所有的i+p[i]放进一个线段树中。维护max。
然后枚举字符串中心i,在max(1,i-n)到(i-1)的区间内找一个最左边且符合答案的的一个点j,那么再与答案比较就行了。
怎么在线段树中找这一个点?
首先找出所有满足要求的区间,然后在这些区间中再根据区间的最大值,找到所有符合的点就好了。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=500007;
int i,j,k,l,t,n,m,ans,len,limit,id;
char s[maxn],st[maxn];
int p[maxn];
struct node{
    int da;
}tree[maxn*3];
void build(int x,int l,int r){
    if(l==r){
        tree[x].da=p[l]+l;
    }
    else{
        int mid=(l+r)/2;
        build(x*2,l,mid);
        build(x*2+1,mid+1,r);
        tree[x].da=max(tree[x*2].da,tree[x*2+1].da);
    }
}
void zhao(int x,int l,int r,int d){
    if(l==r){
        if(p[l]+l>=d)ans=max(i-l,ans);
    }
    else{
        int mid=(l+r)/2;
        if(tree[x*2].da>=d)zhao(x*2,l,mid,d);
        else zhao(x*2+1,mid+1,r,d);
    }
}
void find(int x,int l,int r,int y,int z,int d){
    if(z<y)return;
    if(l==y&&r==z){
        if (tree[x].da>=d)zhao(x,l,r,d);
    }
    else{
        int mid=(l+r)/2;
        if(z<=mid) find(x*2,l,mid,y,z,d);
        else if(y>mid) find(x*2+1,mid+1,r,y,z,d);
        else{
            find(x*2,l,mid,y,mid,d),find(x*2+1,mid+1,r,mid+1,z,d); 
        }
    }
}
int main(){
    scanf("%s",st+1);
    m=strlen(st+1);
    s[1]='#';
    n=1;
    fo(i,1,m){
        s[++n]=st[i];
        s[++n]='#';
    }
    fo(i,1,m){
        s[++n]=st[i];
        s[++n]='#';
    }
    fo(i,1,n){
        if(limit>i) p[i]=min(p[2*id-i],limit-i);
        else p[i]=1;
        while(i-p[i]&&i+p[i]<=n&&s[i-p[i]]==s[i+p[i]])++p[i];
        if(i+p[i]>limit){
            limit=i+p[i];
            id=i;
        }
    }
    fo(i,1,n) p[i]--;
    build(1,1,n);
    fo(i,1,n){
        int o=i-p[i],q=max(1,i-m);
        find(1,1,n,q,i-1,o);
    }
    printf("%d\n",ans);
}

你可能感兴趣的:(线段树,项链,manachar,GDKOI2016)