4310: 跳蚤
题解:
这题有一个很显然的性质是字符串越长字典序越大
考虑二分答案贪心判断
由于最大的一定是后缀,所以从后向前判断,每次加入一个后缀
用hash比较大小(就是二分判断是否相同比较第一个不相同字符)
代码:
#include <bits/stdc++.h> #define ll long long #define ull unsigned ll #define rint register ll #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) using namespace std; const ll N=1.1e6; char s[N]; ll size[N],len[N],ch[N][26],sum[N]; ull s1[N],now[N],d[N],c[N]; ll lst=1,node=1,t[N],a[N],fa[N],k,kk,l; ll cnt; void extend(ll c) { ll f=lst,p=++node; lst=p; len[p]=len[f]+1; size[p]=1; while (f&&!ch[f][c]) ch[f][c]=p,f=fa[f]; if (!f) { fa[p]=1; return;}; ll x=ch[f][c],y=++node; if (len[f]+1==len[x]) {fa[p]=x; node--;return;}; len[y]=len[f]+1; fa[y]=fa[x]; fa[x]=fa[p]=y; memcpy(ch[y],ch[x],sizeof(ch[x])); while (f&&ch[f][c]==x) ch[f][c]=y,f=fa[f]; } void js(ll x) { if (size[x]>=k) return; k-=size[x]; rep(i,0,25) if (sum[ch[x][i]]>=k) { s1[++cnt]=i+1; js(ch[x][i]); return; } else k-=sum[ch[x][i]]; } bool bj(ll h1,ll t1) { ll t2,t; t2=t=min(t1-h1+1,cnt); ll h=0; while (h<t) { ll mid=(h+t+1)/2; if (c[mid]==now[h1+mid-1]-d[mid]*now[h1-1]) h=mid; else t=mid-1; } h++; if (h>t2) if ((t1-h1+1)<=cnt) return(1); else return(0); else return(s[h1+h-2]-'a'+1<s1[h]); } bool check(ll x) { k=x; cnt=0; js(1); for (ll i=1;i<=cnt;i++) c[i]=c[i-1]*26+s1[i]; ll k1=0; ll t=l; dep(i,l,1) { if (bj(i,t)) continue; else { if (i==t) return(0); t=i,k1++; } } k1++; if (k1>kk) return(0); else return(1); } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); cin>>kk>>s; l=strlen(s); d[0]=1; rep(i,1,l) d[i]=d[i-1]*26; rep(i,1,l) extend(s[i-1]-'a'); rep(i,1,l) now[i]=now[i-1]*26+s[i-1]-'a'+1; rep(i,1,node) t[len[i]]++; rep(i,1,node) t[i]+=t[i-1]; rep(i,1,node) a[t[len[i]]--]=i; dep(i,node,1) { ll x=a[i]; size[x]=1; } size[0]=size[1]=0; dep(i,node,1) { ll x=a[i]; sum[x]=size[x]; rep(j,0,25) sum[x]+=sum[ch[x][j]]; } check(2); ll h=1,t=sum[1]; while (h<t) { ll mid=(h+t)/2; if (check(mid)) t=mid; else h=mid+1; } k=h; cnt=0; js(1); rep(i,1,cnt) { char cc='a'+s1[i]-1; cout<<cc; } return 0; }