版权声明:2333 https://blog.csdn.net/liangzihao1/article/details/82083066
题目描述
为了提高智商,ZJY开始学习弦论。这一天,她在《String theory》中看到了这样一道问题:对于一个给定的长度为n的字符串,求出它的第k小子串是什么。你能帮帮她吗?
输入输出格式
输入格式:
第一行是一个仅由小写英文字母构成的字符串s
第二行为两个整数t和k,t为0则表示不同位置的相同子串算作一个,t为1则表示不同位置的相同子串算作多个。k的意义见题目描述。
输出格式:
输出数据仅有一行,该行有一个字符串,为第k小的子串。若子串数目不足k个,则输出-1。
输入输出样例
输入样例#1:
aabc
0 3
输出样例#1:
aab
输入样例#2:
aabc
1 3
输出样例#2:
aa
输入样例#3:
aabc
1 11
输出样例#3:
-1
说明
数据范围
对于
的数据,
。
对于
的数据,
。
对于
的数据,
。
分析:
我们可以对这个串建后缀自动机。如果
,每个点的
为
,否则为
集大小。因为每一条路径都可以代表一个字符串,我们在
上跑出每个点为前缀的字符串有多少个。然后像权值线段树求第
大一样选择走哪条边,不过要先减掉当前点的
,
号节点的
不用减,因为不存在这样的串。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
const int maxn=1e6+7;
using namespace std;
char s[maxn],ans[maxn];
int n,T,k,cnt,num;
int size[maxn],top[maxn],b[maxn],sum[maxn];
queue <int> q;
struct node{
int len,fail;
int son[26];
}t[maxn];
void build_sam()
{
cnt=1;
int now=1,p,q,clone;
for (int i=0;i<n;i++)
{
int c=s[i]-'a';
p=now;
now=++cnt;
t[now].len=t[p].len+1;
size[now]=1;
while (p&&(!t[p].son[c])) t[p].son[c]=now,p=t[p].fail;
if (!p) t[now].fail=1;
else
{
q=t[p].son[c];
if (t[p].len+1==t[q].len) t[now].fail=q;
else
{
clone=++cnt;
t[clone]=t[q];
t[clone].len=t[p].len+1;
t[now].fail=t[q].fail=clone;
while (p&&(t[p].son[c]==q)) t[p].son[c]=clone,p=t[p].fail;
}
}
}
}
void prework()
{
for (int i=1;i<=cnt;i++) b[t[i].len]++;
for (int i=1;i<=n;i++) b[i]+=b[i-1];
for (int i=1;i<=cnt;i++) top[b[t[i].len]--]=i;
for (int i=cnt;i>0;i--) size[t[top[i]].fail]+=size[top[i]];
for (int i=cnt;i>0;i--)
{
int x=top[i];
if (!T) size[x]=1;
sum[x]=size[x];
for (int j=0;j<26;j++) sum[x]+=sum[t[x].son[j]];
}
}
void solve()
{
q.push(1);
while (!q.empty())
{
int x=q.front();
q.pop();
if (x!=1)
{
if (k<=size[x]) return;
k-=size[x];
}
for (int i=0;i<26;i++)
{
if (sum[t[x].son[i]]>=k)
{
ans[++num]='a'+i;
q.push(t[x].son[i]);
break;
}
else k-=sum[t[x].son[i]];
}
}
}
int main()
{
scanf("%s",s);
scanf("%d%d",&T,&k);
n=strlen(s);
build_sam();
prework();
solve();
if (!num) printf("-1");
else
{
for (int i=1;i<=num;i++) printf("%c",ans[i]);
}
}