Description

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

Input

第一行是一个仅由小写英文字母构成的字符串S

第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个。K的意义如题所述。

Output

输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1

Sample Input

aabc

0 3

Sample Output

aab

HINT

N<=5*10^5

T<2

K<=10^9


思路

看这道题是处理K小字串,果断上后缀自动机啊

然后考虑怎么统计答案

如果T是0,那么可以每一个节点的大小是1,否则大小是right集合大小

然后toposort之后反向DP出经过这条转移边可以有多少种字串

然后就可以直接贪心了


toposort的数组也要开串长两倍啊啊啊


#include<bits/stdc++.h>
using namespace std;
#define fu(a,b,c) for(int a=b;a<=c;++a)
#define fd(a,b,c) for(int a=b;a>=c;--a)
const int CHARSET_SIZE=26;
#define N 500010
struct Node{
int ch[CHARSET_SIZE],prt;
int maxl,right;
Node(int maxl=0,int right=0):ch(),prt(0),maxl(maxl),right(right){}
}t[N<<1];
int root,last,cur;
int topo[N<<1],buc[N];
int newnode(int maxl=0,int right=0){t[++cur]=Node(maxl,right);return cur;}
void init(){cur=0;root=last=newnode();}
void extend(int c){
int u=newnode(t[last].maxl+1,1),v=last;
for(;v&&!t[v].ch[c];v=t[v].prt)t[v].ch[c]=u;
if(!v){t[u].prt=root;}
else if(t[t[v].ch[c]].maxl==t[v].maxl+1){
t[u].prt=t[v].ch[c];
}else{
int n=newnode(t[v].maxl+1,0),o=t[v].ch[c];
memcpy(t[n].ch,t[o].ch,sizeof(t[o].ch));
t[n].prt=t[o].prt;
t[o].prt=t[u].prt=n;
for(;v&&t[v].ch[c]==o;v=t[v].prt)t[v].ch[c]=n;
}
last=u;
}
void toposort(){
int maxv=0;
fu(i,1,cur){
++buc[t[i].maxl];
maxv=max(maxv,t[i].maxl);
}
fu(i,1,maxv)buc[i]+=buc[i-1];
fu(i,1,cur)topo[buc[t[i].maxl]--]=i;
fu(i,1,maxv)buc[i]=0;
}
void cal_right(){
toposort();
fd(i,cur,1){
int p=topo[i];
t[t[p].prt].right+=t[p].right;
}
}
char c[N],ans[N];
int T,K,dp[N<<1];
int main(){
scanf("%s",c+1);
scanf("%d%d",&T,&K);
int len=strlen(c+1);
init();
fu(i,1,len)extend(c[i]-'a');
cal_right();
fu(i,2,cur)dp[i]=T?t[i].right:1;
fd(i,cur,1)
fu(j,0,25)
dp[topo[i]]+=dp[t[topo[i]].ch[j]];
if(K>dp[1]){printf("-1");return 0;}
int now=1,siz=0;
while(1){
int tmp=T?t[now].right:1;
if(now==1)tmp=0;
if(K<=tmp)break;
K-=tmp;
fu(i,0,25)if(t[now].ch[i]){
int v=t[now].ch[i];
if(dp[v]>=K){ans[++siz]=i+'a';now=v;break;}
else K-=dp[v];
}
}
fu(i,1,siz)printf("%c",ans[i]);
return 0;
}

BZOJ3998 TJOI2015 弦论 【后缀自动机】【贪心】的更多相关文章

  1. [bzoj3998][TJOI2015]弦论-后缀自动机

    Brief Description 给定一个字符串, 您需要求出他的严格k小子串或非严格k小子串. Algorithm Design 考察使用后缀自动机. 首先原串建SAM, 然后如果考察每个状态代表 ...

  2. 【BZOJ3998】[TJOI2015]弦论 后缀自动机

    [BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T ...

  3. 【bzoj3998】[TJOI2015]弦论 后缀自动机+dp

    题目描述 对于一个给定长度为N的字符串,求它的第K小子串是什么. 输入 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置 ...

  4. 【BZOJ-3998】弦论 后缀自动机

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2018  Solved: 662[Submit][Status] ...

  5. BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2152  Solved: 716[Submit][Status] ...

  6. BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串

    http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串 ...

  7. BZOJ 3998 TJOI2015 弦论 后缀自动机+DAG上的dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3998 题意概述:对于一个给定长度为N的字符串,求它的第K小子串是什么,T为0则表示不同位置 ...

  8. BZOJ 3998 [TJOI2015]弦论 ——后缀自动机

    直接构建后缀自动机. 然后. 然后只需要再后缀自动机的go树上类似二分的方法进行查找即可,实际上是“26分”. 然后遇到了处理right集合的问题,然后觉得在go和parent树上上传都是可以的,毕竟 ...

  9. [TJOI2015]弦论(后缀自动机)

    /* 一道在树上乱搞的题目 建立出parent树来, 然后就能搞出每个节点往后能扩展出几个串, 至于位置不同算同一个的话就强制让right集合大小为1即可 然后在树上类比权值线段树找第k大26分统计一 ...

  10. BZOJ.3998.[TJOI2015]弦论(后缀自动机)

    题目链接 \(Description\) 给定字符串S,求其第K小子串.(若T=0,不同位置的相同子串算1个:否则算作多个) \(Solution\) 建SAM,处理出对于每个节点,它和它的所有后继包 ...

随机推荐

  1. c++之迭代器失效

    1.首先从一到题目开始谈说起迭代器失效.有时我们很自然并且自信地 用下面方法删除vector元素: #include <iostream>#include <stdio.h># ...

  2. .net 下的 HttpRuntime.Cache 应用

    using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using Syste ...

  3. 一些常用的CDN列表

    Microsoft Ajax Content Delivery Network 点击查看详细列表

  4. [Spring]Spring Mvc实现国际化/多语言

    1.添加多语言文件*.properties F64_en_EN.properties详情如下: F60_G00_M100=Please select data. F60_G00_M101=Are yo ...

  5. 【BZOJ1061】【NOI2008】志愿者招募

    [BZOJ1061][NOI2008]志愿者招募 题面 BZOJ 题解 我们设每类志愿者分别招募了\(B[i]\)个 那么,我们可以得到一系列的方程 \[\sum_{S[i]\leq x\leq T[ ...

  6. C++(二十九) — new 和 delete

    1.基本用法,定义变量.数组.对象 class test { public: test(int a_, int b_) { a = a_; b = b_; cout << "构造 ...

  7. python 爬虫005-爬虫实例

    实例一:扒取猫眼电影TOP100 的信息 #!/usr/bin/env python # -*- coding: utf-8 -*- """ 扒取猫眼电影TOP100 的 ...

  8. 键盘对应数字-keycode值大全(转)

    event.keycode值大全   keycode 8 = BackSpace BackSpace    keycode 9 = Tab Tab    keycode 12 = Clear    k ...

  9. AsyncCallback 异步回调委托

    js是单线程语言,单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务.如果前一个任务耗时很长,后一个任务就不得不一直等着. 如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多 ...

  10. 《OpenCL编程指南》之 与Direct3D互操作

    介绍OpenCL与D3D 10之间的互操作. 1.初始化OpenCL上下文实现Direct3D互操作 OpenCL共享由pragma cl_khr_d3d10_sharing启用: #pragma O ...