bzoj4310: 跳蚤

来源:互联网 发布:安全员c证网络查询 编辑:程序博客网 时间:2024/06/02 19:28

二分+后缀数组;

#include<bits/stdc++.h>#define rep(i,k,n) for(int i=k;i<(n);i++)#define rep2(i,k,n)for(int i=k;i>=(n);i--)using namespace std;const int maxn=100105;typedef long long ll;int K,sa[maxn],he[maxn],p1[maxn],p2[maxn],c[maxn],rank[maxn],sig=500,n,rmq[maxn][18],pw[18],Log[maxn],top=0,id[maxn],len;ll g[maxn];char s[maxn];void build_sa(){    int* x=p1;int* y=p2;    rep(i,0,n)c[x[i]=s[i]]++;    rep(i,1,sig)c[i]+=c[i-1];    rep2(i,n-1,0)sa[--c[x[i]]]=i;    for(int h=1;h<=n;h<<1){int t=0;        rep(i,n-h,n)y[t++]=i;rep(i,0,n)if(sa[i]>=h)y[t++]=sa[i]-h;        rep(i,0,sig)c[i]=0;        rep(i,0,n)c[x[y[i]]]++;        rep(i,1,sig)c[i]+=c[i-1];        rep2(i,n-1,0)sa[--c[x[y[i]]]]=y[i];        swap(x,y);t=0;        x[sa[0]]=0;        rep(i,1,n)x[sa[i]]=y[sa[i]]==y[sa[i-1]] && y[sa[i]+h]==y[sa[i-1]+h] ? t : ++t;        t++;if(t>=n)break;        sig=t;    }    rep(i,0,n)rank[sa[i]]=i;    int j=0;    rep(i,0,n){if(!rank[i])continue;    if(j)j--;        int k=sa[rank[i]-1];        while(s[i+j]==s[k+j])j++;        he[rank[i]]=j;    }}void init(){pw[0]=1;    rep(i,1,17)pw[i]=pw[i-1]<<1;    rep(i,2,maxn)Log[i]=Log[i>>1]+1;    rep(i,0,n)rmq[i][0]=he[i];    rep(i,1,17)rep(j,0,n)if(j+pw[i-1]<n)rmq[j][i]=min(rmq[j][i-1],rmq[j+pw[i-1]][i-1]); //if(j+pw[i-1]<n)    ll ss=0;    rep(i,0,n){ss+=n-sa[i]-he[i];g[++top]=ss;id[top]=i;}}int lcp(int x,int y){if(x==y)return n-x; //x=rank[x],y=rank[y];if(x>y)swap(x,y);    int t=Log[y-x];    return min(rmq[x+1][t],rmq[y-pw[t]+1][t]); //}int nowl,nowr,ansl,ansr;void kth(ll k){int t=lower_bound(g+1,g+top+1,k)-g;    nowl=sa[id[t]];nowr=nowl+he[id[t]]+k-g[t-1]-1;len=nowr-nowl+1;}bool pan(int l,int r){    int t=min(lcp(l,nowl),min(len,r-l+1));    if(t==r-l+1 && t<=len)return 1;    if(t==len)return 0;    return s[l+t]<=s[nowl+t];}bool ok(){int k=0;    int i=n-1,j=n-1;    while(i>=0){        while(j>=0 && pan(j,i))j--;        if(i==j)return 0;        k++;i=j;    }    return (k<=K);}int main(){//freopen("in.in","r",stdin);    scanf("%d",&K);    scanf("%s",s);n=strlen(s);    build_sa();    init();    ll l=0,r=g[top];  //    while(l<=r){        ll mid=(l+r)>>1;        kth(mid);        if(ok()){ansl=nowl,ansr=nowr,r=mid-1;}        else l=mid+1;    }    rep(i,ansl,ansr+1)putchar(s[i]);    return 0;}
0 0