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;
}

 

posted @ 2018-07-23 10:21  尹吴潇  阅读(156)  评论(0编辑  收藏  举报