您的位置:首页 > 其它

bzoj 3998: [TJOI2015]弦论 后缀自动机

2017-03-08 20:31 375 查看

题目大意:

对于一个给定长度为N的字符串,求它的第K小子串是什么。

题解:

这道题我们可以类比着bzoj 2882: 工艺来做

那道题是求最小的一个字符串,而这道题是要求一个k小的字符串
所以我们瞎搞一搞就好了啊...像在平衡树上查询k小一样.

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(ll &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const ll maxn = 500010;
struct Node{
int nx[26];
int fa,len;
}T[maxn<<1];
int last,nodecnt;
ll siz[maxn<<1];
int num[maxn<<1];
void init(){
last = nodecnt = 0;
T[0].fa = -1;T[0].len = 0;
}
void insert(char cha){
int c = cha - 'a',cur = ++ nodecnt,p;
T[cur].len = T[last].len+1;
for(p=last;p!=-1 && !T[p].nx[c];p=T[p].fa) T[p].nx[c] = cur;
if(p == -1) T[cur].fa = 0;
else{
int q = T[p].nx[c];
if(T[q].len == T[p].len + 1) T[cur].fa = q;
else{
int co = ++ nodecnt;
T[co] = T[q];T[co].len = T[p].len + 1;
for(;p!=-1&&T[p].nx[c] == q;p=T[p].fa) T[p].nx[c] = co;
T[cur].fa = T[q].fa = co;
}
}last = cur;
++num[last];
}
inline void build(char *s){
init();int len = strlen(s);
for(int i=0;i<len;++i) insert(s[i]);
}
int q[maxn<<1],l,r;
bool vis[maxn<<1];
void calc_num(int ty){
l = 0;r = -1;
q[++r] = 0;vis[0] = true;
while(l <= r){
int u = q[l++];
for(int c=0;c<26;++c){
if(T[u].nx[c] && !vis[T[u].nx[c]]){
vis[T[u].nx[c]] = true;
q[++r]  = T[u].nx[c];
}
}
}
for(int i=r;i>=1;--i){
if(ty == 0) num[q[i]] = (bool)num[q[i]];
num[T[q[i]].fa] += num[q[i]];
}
}
void dfs(int u){
vis[u] = true;
siz[u] = num[u];
for(int c=0;c<26;++c){
if(T[u].nx[c]){
if(!vis[T[u].nx[c]]) dfs(T[u].nx[c]);
siz[u] += siz[T[u].nx[c]];
}
}return;
}
bool flag = false;
void find(int u,ll k){
if(k <= num[u]) return;
k -= num[u];
for(int c=0;c<26;++c){
if(T[u].nx[c]){
if(k <= siz[T[u].nx[c]]){
flag = true;
putchar(c+'a');
find(T[u].nx[c],k);
return;
}k -= siz[T[u].nx[c]];
}
}return;
}
char s[maxn<<1];
int main(){
scanf("%s",s);build(s);
ll T,K;read(T);read(K);
calc_num(T);memset(vis,0,sizeof vis);
num[0] = 0;dfs(0);
if(siz[0] < K) return puts("-1");
find(0,K);
getchar();getchar();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: