洛谷P3975

链接:

 https://www.luogu.com.cn/problem/P3975

题意如题

题解:先DFS累加后面的串出现的次数,

然后跑trans找就可以了

当不同位置看作同一个字串时,显然这时候每个状态只出现一次,出现次数siz就是1;(同时注意设置clone节点的siz,因为建立时clone节点的siz是0,这时候把所有状态的siz都更新成1就行了)(这是个坑)

然后不同位置看成不同字串时,预处理(DFS按link累加出现的次数)

然后按字符串从小到大找就可以了

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,a,n) for(int i=n;i>=a;--i)
#define pb push_back
#define fi first
#define se second
#define io std::ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;

ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
ll qpow(ll a,ll n)
{
    ll r=1%P;
    for (a%=P; n; a=a*a%P,n>>=1)if(n&1)r=r*a%P;
    return r;
}
const int maxn=2e6;

struct Suffix_Automata {
  int maxlen[maxn], trans[maxn][26], link[maxn], Size, Last;
  int siz[maxn];
  int t[maxn],A[maxn];
  Suffix_Automata() { Size = Last = 1; }
  inline void Extend(int id) {
    int cur = (++ Size), p;
    siz[Size]=1;
    maxlen[cur] = maxlen[Last] + 1;
    for (p = Last; p && !trans[p][id]; p = link[p]) trans[p][id] = cur;
    if (!p) link[cur] = 1;
    else {
      int q = trans[p][id];
      if (maxlen[q] == maxlen[p] + 1) link[cur] = q;
      else {
        int clone = (++ Size);
        maxlen[clone] = maxlen[p] + 1;
        memcpy(trans[clone], trans[q],sizeof(trans[q]));
        link[clone] = link[q];
        for (; p && trans[p][id] == q; p = link[p]) trans[p][id] = clone;
        link[cur] = link[q] = clone;
      }
    }
    Last = cur;
  }
  int sum[maxn];

  void buildtree(int x)
  {
      for(int i=1;i<=Size;i++) t[maxlen[i]]++;
      for(int i=1;i<=Size;i++) t[i]+=t[i-1];
      for(int i=1;i<=Size;i++) A[t[maxlen[i]]--]=i;
      for(int i=Size;i>=1;i--)
      {   int now=A[i];
          int fa=link[now];
          if(x)
          siz[fa]+=siz[now];
          else
          siz[now]=1;
      }
      for(int i=Size;i>=1;i--)
      {
          int now=A[i];
          sum[now]=siz[now];
          for(int j=0;j<26;j++)
          {
           sum[now]+=sum[trans[now][j]];
          }
      }
  }
  void _find(int x)
  {   int now=1;
      if(x>sum[1])
       {
        cout<<-1;
        return ;
       }
        while (x>0)
        {
            int p=0;
            while (x>sum[trans[now][p]])
            {
                x-=sum[trans[now][p]];
                p++;
            }
            now=trans[now][p];
            putchar('a'+p);
            x-=siz[now];
        }
  }
} T;
int main()
{
     char s[maxn];
     cin>>s+1;
     int t,k;
     int n=strlen(s+1);
     for(int i=1;i<=n;i++)
     {
       T.Extend(s[i]-'a');
     }
     cin>>t>>k;
     T.buildtree(t);
     T._find(k);



}

 

posted @ 2020-09-10 11:12  摸鱼选手LLF  阅读(148)  评论(0编辑  收藏  举报