# 【BZOJ-4310】跳蚤 后缀数组 + ST表 + 二分

## 4310: 跳蚤

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 180  Solved: 83
[Submit][Status][Discuss]

## Sample Input

13
bcbcbacbbbbbabbacbcbacbbababaabbbaabacacbbbccaccbcaabcacbacbcabaacbccbbcbcbacccbcccbbcaacabacaaaaaba

cbc

S的长度<=100000

## Code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 1000100
char S[maxn]; int SA[maxn],len,K;
int wa[maxn],wb[maxn],ws[maxn],wv[maxn];
long long tot;
int L,R;
inline int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
inline void DA(char *r,int *sa,int n,int m)
{
int p,*x=wa,*y=wb,*t;
for (int i=0; i<m; i++) ws[i]=0;
for (int i=0; i<n; i++) ws[x[i]=r[i]]++;
for (int i=1; i<m; i++) ws[i]+=ws[i-1];
for (int i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
p=1; for (int j=1; p<n; j*=2,m=p)
{
p=0; for (int i=n-j; i<n; i++) y[p++]=i;
for (int i=0; i<n; i++) if (sa[i]>=j) y[p++]=sa[i]-j;
for (int i=0; i<n; i++) wv[i]=x[y[i]];
for (int i=0; i<m; i++) ws[i]=0;
for (int i=0; i<n; i++) ws[wv[i]]++;
for (int i=1; i<m; i++) ws[i]+=ws[i-1];
for (int i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
t=x,x=y,y=t;p=1;x[sa[0]]=0;
for (int i=1; i<n; i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
}
int rank[maxn],height[maxn];
inline void calheight(char *r,int *sa,int n)
{
int k=0;
for (int i=1; i<=n; i++) rank[sa[i]]=i;
for (int i=0; i<n; height[rank[i++]]=k)
{k?k--:0;for (int j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);}
}
int log2[maxn]; int dp[maxn][21];
void ST(int n)
{
log2[0]=-1;
for (int i=1; i<=n; i++)
if (i&(i-1)) log2[i]=log2[i-1];
else log2[i]=log2[i-1]+1;
for (int i=1; i<=n; i++) dp[i][0]=height[i];
for (int j=1; (1<<j)<=len; j++)
for (int i=1; i+(1<<j)-1<=n; i++)
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int RMQ(int l,int r)
{
int tmp=log2[r-l+1];
return min(dp[l][tmp],dp[r-(1<<tmp)+1][tmp]);
}
int LCP(int l,int r)
{
if (l==r) return len-l;
l=rank[l]; r=rank[r];
if (l>r) swap(l,r); l++;
return RMQ(l,r);
}
void Get(long long k)
{
for (int i=1; i<=len; i++)
if ((long long)(len-SA[i]-height[i])<k) k-=(long long)(len-SA[i]-height[i]);
else {L=SA[i],R=SA[i]+height[i]+k-1; break;}
}
bool Compare(int l1,int r1,int l2,int r2)
{
int len1=r1-l1+1,len2=r2-l2+1,lcp=LCP(l1,l2);
if (len1<=len2 && lcp>=len1) return 1;
if (len1>len2 && lcp>=len2) return 0;
if (lcp>=len1 && lcp>=len2) return len1>len2? 0:1;
return S[l1+lcp]>S[l2+lcp]? 0:1;
}
int Check()
{
int cnt=1,last=len-1;
for (int i=len-1; i>=0; i--)
{
if (S[i]>S[L]) return 0;
if (!Compare(i,last,L,R)) ++cnt,last=i;
if (cnt>K) return 0;
}
return 1;
}
int main()
{
scanf("%d",&K); scanf("%s",S);
len=strlen(S); S[len]=0;
DA(S,SA,len+1,200); calheight(S,SA,len);
ST(len);
for (int i=1; i<=len; i++) tot+=len-SA[i]-height[i];
//    printf("%d\n",tot);
long long l=1,r=tot;
while (l<=r)
{
long long mid=(l+r)>>1;
Get(mid);
//          printf("L=%d R=%d\n",L,R);
if (Check()) r=mid-1; else l=mid+1;
//          printf("%I64d %I64d\n",l,r);
}
Get(r+1);
for (int i=L; i<=R; i++) putchar(S[i]);
return 0;
}

——It's a lonely path. Don't make it any lonelier than it has to be.
posted @ 2016-07-28 10:49  DaD3zZ  阅读(710)  评论(0编辑  收藏  举报