題目描述
爲了提高智商,ZJY開始學習弦論。這一天,她在《 String theory》中看到了這樣一道問題:對於一個給定的長度爲n的字符串,求出它的第k小子串是什麼。你能幫幫她嗎?
輸入格式
第一行是一個僅由小寫英文字母構成的字符串s
第二行爲兩個整數t和k,t爲0則表示不同位置的相同子串算作一個,t爲1則表示不同位置的相同子串算作多個。k的意義見題目描述。
輸出格式
輸出數據僅有一行,該行有一個字符串,爲第k小的子串。若子串數目不足k個,則輸出-1。
學習了後綴自動機 也終於A了這道感覺很麻煩的題= = 寫個博客慶祝一下
求第k小串的套路就像是在主席樹上面查詢第k小數,首先用後綴自動機處理出每個節點後續的子串的個數,然後對於每個節點枚舉26條邊轉移即可 一個節點所表示的串的出現次數即爲endpos集合的size,若對於t = 1相同子串不同位置算不同子串(除複製節點外,其他節點初始|endpos|大小設置爲1) 需要在後綴樹上面拓撲dp t = 0的話 每個節點只表示它的最長串 所以每個節點的值爲1
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#define Sheryang main
typedef long long ll;
#define HEAP(...) priority_queue<__VA_ARGS__ >
#define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
template<class T> inline T min(T &x,const T &y){return x>y?y:x;}
template<class T> inline T max(T &x,const T &y){return x<y?y:x;}
//#define getchar()(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
//char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();if(c == '-')Nig = -1,c = getchar();while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();return Nig*x;}
#define read read()
const int maxn = 1e6+7;
const int mod = 1e9+7;
/** keep hungry and keep calm! **/
int nxt[maxn],head[maxn],to[maxn],cnt;
void add(int u,int v){
nxt[++cnt] = head[u];
head[u] = cnt;
to[cnt] = v;
}
struct Sam{
int trans[maxn][26],fail[maxn];
int maxlen[maxn],minlen[maxn];
int sz,last,vis[maxn];
ll sum[maxn],num[maxn];
Sam(){
sz = last = 1;
}
void ins(int id){
int cur = ++sz,p = last;
num[cur] = 1;
maxlen[cur] = maxlen[last] + 1;
while(p && trans[p][id] == 0){
trans[p][id] = cur;
p = fail[p];
}
if(p == 0){
fail[cur] = 1;
}else{
int q = trans[p][id];
if(maxlen[q] == maxlen[p] + 1){
fail[cur] = q;
}else{
int clone = ++sz;
memcpy(trans[clone],trans[q],sizeof trans[q]);
fail[clone] = fail[q];
fail[cur] = fail[q] = clone;
maxlen[clone] = maxlen[p] + 1;
while(trans[p][id] == q){
trans[p][id] = clone;
p = fail[p];
}
}
}
last = cur;
}
void init(){
for(int i=1;i<=sz;i++) head[i] = -1;
for(int i=2;i<=sz;i++){
add(fail[i],i);
}
}
void dfs(int u){
for(int i=head[u];~i;i = nxt[i]){
dfs(to[i]);
num[u] += num[to[i]];
}
}
void calc(int u){
sum[u] = num[u];
vis[u] = 1;
for(int i=0;i<26;i++){
int v = trans[u][i];
if(v != 0){
if(vis[v] == 0)calc(v);
sum[u] += sum[v];
}
}
}
void Fuck(int u,int k){
int rt = 1;
while(k){
for(int i=0;i<26;i++){
int v = trans[rt][i];
if(v != 0){
if(k <= sum[v]){
putchar('a' + i);
k -= num[v];
rt = v;
break;
}else{
k -= sum[v];
}
}
}
}
}
void Solve(){
int op = read , k = read;
init();
if(op == 1){
dfs(1);
}else{
for(int i=1;i<=sz;i++) num[i] = 1;
}
num[1] = 0;
calc(1);
if(k > sum[1]){
printf("-1");
}else{
Fuck(1,k);
}
puts("");
}
}Sam;
char s[maxn];
int Sheryang(){
scanf("%s",s);
for(int i=0;s[i];i++){
Sam.ins(s[i]-'a');
}
Sam.Solve();
return 0;
}