【题目地址】点击打开链接
【题目大意】
给定一个字符串s,每次提问它的第k小子串。
起始位置不同的相同子串看做不同字串。
【分析】
这道题的做法跟我博客上的上一题差不多。只需要改一个地方:
x.sz=x.same+sigma(y.sz) y是x的儿子
【代码】
/****************************
ID:Ciocio
LANG:C++
DATE:2014-2-2
TASK:cf 128B String
****************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define MAXN 100010
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rrep(i,b,a) for(int i=b;i>=a;--i)
#define sf scanf
#define pf printf
#define LL long long
struct SAM{
int tot,last,m;
int pre[MAXN<<1],go[MAXN<<1][26],step[MAXN<<1];
LL sz[MAXN<<1],same[MAXN<<1];
int head[MAXN<<1],next[MAXN*2*26],ch[MAXN*2*26];
void new_node(int s){
step[++tot]=s;
pre[tot]=0;
same[tot]=0;
memset(go[tot],0,sizeof go[tot]);
}
void build(char* s){
tot=0;last=1;
new_node(0);
int n=strlen(s);
rep(i,0,n-1){
new_node(step[last]+1);
same[tot]=1;
int c=s[i]-'a';
int p=last,np=tot,q,nq;
for(;p&&!go[p][c];p=pre[p]) go[p][c]=np;
if(!p)
pre[np]=1;
else{
q=go[p][c];
if(step[q]==step[p]+1) pre[np]=q;
else{
new_node(step[p]+1);
same[tot]=0;
nq=tot;
memcpy(go[nq],go[q],sizeof go[q]);
pre[nq]=pre[q];
pre[np]=
pre[q]=nq;
for(;p&&go[p][c]==q;p=pre[p]) go[p][c]=nq;
}
}
last=np;
}
m=0;
rep(i,1,tot)
rrep(j,25,0){
if(go[i][j]){
ch[++m]=j;
next[m]=head[i];
head[i]=m;
}
}
}
void get_same(){
queue <int> q;
vector <int> degree(tot+1);
rep(i,1,tot) degree[pre[i]]++;
rrep(i,tot,1)
if(!degree[i])
q.push(i);
while(!q.empty()){
int x=q.front();
q.pop();
if(!--degree[pre[x]]) q.push(pre[x]);
same[pre[x]]+=same[x];
}
}
void dfs(int x){
sz[x]=same[x];
for(int i=head[x];i;i=next[i]){
int y=go[x][ch[i]];
if(y&&!sz[y]) dfs(y);
sz[x]+=sz[y];
}
}
void findkth(int k){
int p=1;
while(k>0){
for(int j=head[p];j;j=next[j]){
int i=ch[j];
if(k<=sz[go[p][i]]){
k-=same[go[p][i]];
putchar(i+'a');
p=go[p][i];
break;
}
else{
k-=sz[go[p][i]];
}
}
}
cout<<endl;
}
};
char S[MAXN];
int k;
SAM run;
int main(){
sf("%s%d",S,&k);
run.build(S);
run.get_same();
run.dfs(1);
int cnt=0;
if(k>run.sz[1]-run.same[1])
pf("No such line.\n");
else
run.findkth(k);
return 0;
}