您的位置:首页 > 其它

项链

2016-03-01 22:10 225 查看

题目大意

对于一个项链,每个珠子上都有字符。删去最少的一段后,使得剩余项链对称(对对称意义不明可参见GDKOI2015 DAY1 T1)

manacher+数据结构

复制一份原串。

那么显然删除后的串可以对应到新串的一段。

对新串做一次manacher,那么对于两个回文中心i和j,如果j-i<=n,且i+f[i]>=j-f[j],那么可以组成一个j-i长度的对称项链。对于这个用各种数据结构维护即可。

[code]#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100000+10;
int f[maxn*4];
int tree[maxn*20];
int i,j,k,l,r,t,n,m,ans,tot;
char ch;
char s[maxn*2],h[maxn*4];
void change(int p,int l,int r,int a,int b){
    if (l==r){
        tree[p]=b;
        return;
    }
    int mid=(l+r)/2;
    if (a<=mid) change(p*2,l,mid,a,b);else change(p*2+1,mid+1,r,a,b);
    tree[p]=max(tree[p*2],tree[p*2+1]);
}
int query(int p,int l,int r,int a,int b){
    if (a>b) return 0;
    if (l==a&&r==b) return tree[p];
    int mid=(l+r)/2;
    if (b<=mid) return query(p*2,l,mid,a,b);
    else if (a>mid) return query(p*2+1,mid+1,r,a,b);
    else return max(query(p*2,l,mid,a,mid),query(p*2+1,mid+1,r,mid+1,b));
}
int main(){
    while (1){
        ch=getchar();
        if (ch<'a'||ch>'z') break;
        s[++n]=ch;
    }
    fo(i,1,n) s[n+i]=s[i];
    h[0]='@';
    h[1]='$';
    fo(i,1,n*2) h[i*2]=s[i],h[i*2+1]='$';
    h[n*4+2]='%';
    j=0;
    f[0]=0;
    fo(i,2,n*4){
        if (i>j+f[j]){
            f[i]=0;
            while (h[i+f[i]+1]==h[i-f[i]-1]) f[i]++;
        }
        else{
            f[i]=min(f[2*j-i],j+f[j]-i);
            while (h[i+f[i]+1]==h[i-f[i]-1]) f[i]++;
        }
        if (i+f[i]>j+f[j]) j=i;
    }
    fo(i,3,n+2) change(1,1,n*4+1,i-f[i],i);
    fo(i,2,n*4){
        ans=max(ans,query(1,1,n*4+1,1,i+f[i])-i);
        if (i+n+1<=n*4) change(1,1,n*4+1,i+n+1-f[i+n+1],i+n+1);
    }
    printf("%d\n",ans);
}


扫描线+并查集

yang神的方法,不懂
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: