zoukankan      html  css  js  c++  java
  • 洛谷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);
    
    
    
    }
  • 相关阅读:
    关于SUID、SGID、Sticky(转载)
    对Linux下TCP连接相关配置的优化记录(转载)
    ACL权限设置(转载)
    如何把一个命令加入到某个用户sudo的列表中(转载)
    菜鸟的逆袭 目标
    菜鸟的逆袭 自我介绍
    Weekly Work from表单练习
    CSS属性display的值及其描述
    CSS Position
    电源防反接保护电路
  • 原文地址:https://www.cnblogs.com/acmLLF/p/13644577.html
Copyright © 2011-2022 走看看