• 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;
    }
  • 相关阅读:
    【机器学习】K-means文本聚类,python
    【机器学习】K-means文本聚类,简单入门版,python
    【python】jiaba分词,停用词分享,stopwords
    【python】jieba分词,去停用词,自定义字典
    【python】jieba分词,简单版
    【python】散点图,读取excel数据,xlrd
    vhost文件配置含义是什么
    羊驼可以吃吗
    PHP中的sublime软件如何用快捷键移动到行尾或者行首
    PHP中单引号,双引号,的区别?
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9353277.html
Copyright © 2020-2023  润新知