链接:
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); }