BZOJ_3998_[TJOI2015]弦论_后缀自动机
BZOJ_3998_[TJOI2015]弦论_后缀自动机
Description
对于一个给定长度为N的字符串,求它的第K小子串是什么。
Input
第一行是一个仅由小写英文字母构成的字符串S
Output
输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1
Sample Input
0 3
Sample Output
HINT
N<=5*10^5
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000050
int ch[N][26],fa[N],dep[N],siz[N],cnt=1,lst=1,f[N];
int ws[N],a[N];
char w[N];
void insert(int x) {
int p=lst,np=++cnt,q,nq;
lst=np; dep[np]=dep[p]+1;
for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
if(!p) fa[np]=1;
else {
q=ch[p][x];
if(dep[q]==dep[p]+1) fa[np]=q;
else {
fa[nq=++cnt]=fa[q];
dep[nq]=dep[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[q]=fa[np]=nq;
for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}
siz[np]=1;
}
void print() {
int i,j;
printf("test-------------------------------------------\n");
for(i=1;i<=cnt;i++) {
printf("p=%d,siz=%d,dep=%d,fa=%d\n",i,siz[i],dep[i],fa[i]);
for(j=0;j<26;j++) {
if(ch[i][j]) {
printf("ch(%d)(%c)=%d\n",i,j+'a',ch[i][j]);
}
}
}
printf("lst=%d\n",lst);
}
int main() {
int T,K;
scanf("%s%d%d",w+1,&T,&K);
int n=strlen(w+1);
int i,j,p;
for(i=1;i<=n;i++) insert(w[i]-'a');
for(i=1;i<=cnt;i++) ws[dep[i]]++;
for(i=1;i<=n;i++) ws[i]+=ws[i-1];
for(i=cnt;i;i--) a[ws[dep[i]]--]=i;
if(T) {
for(i=cnt;i;i--) {
p=a[i]; siz[fa[p]]+=siz[p];
}
}else for(i=cnt;i;i--) siz[a[i]]=1;
for(siz[1]=0,i=cnt;i;i--) {
p=a[i];
for(f[p]=siz[p],j=0;j<26;j++) f[p]+=f[ch[p][j]];
}
if(f[1]<K) puts("-1");
else {
p=1;
while(K>siz[p]) {
K-=siz[p];
for(i=0;i<26;i++) {
if(K<=f[ch[p][i]]) {printf("%c",i+'a'),p=ch[p][i]; break;}
else K-=f[ch[p][i]];
}
}
puts("");
}
}
BZOJ_3998_[TJOI2015]弦论_后缀自动机的更多相关文章
- [bzoj3998][TJOI2015]弦论_后缀自动机
弦论 bzoj-3998 TJOI-2015 题目大意:给定一个字符串,求其$k$小子串. 注释:$1\le length \le 5\cdot 10^5$,$1\le k\le 10^9$. 想法: ...
- 2018.12.15 bzoj3998: [TJOI2015]弦论(后缀自动机)
传送门 后缀自动机基础题. 求第kkk小的子串(有可能要求本质不同) 直接建出samsamsam,然后给每个状态赋值之后在上面贪心选最小的(过程可以类比主席树/平衡树的查询操作)即可. 代码: #in ...
- BZOJ3998 TJOI2015 弦论 【后缀自动机】【贪心】
Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...
- BZOJ3998 [TJOI2015]弦论 【后缀自动机】
题目 对于一个给定长度为N的字符串,求它的第K小子串是什么. 输入格式 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置 ...
- BZOJ3998: [TJOI2015]弦论(后缀自动机,Parent树)
Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...
- [TJOI2015]弦论(后缀自动机)
传送门 题意: 对给定字符串\(s\),求其第\(k\)小子串,重复串被计入以及不被计入这两种情况都需考虑. 思路: 首先构建后缀自动机,之后就考虑在后缀自动机上\(dp\). 我们知道如果要考虑重复 ...
- 【洛谷 P3975】 [TJOI2015]弦论(后缀自动机)
题目链接 建出后缀自动机. T=0,每个子串算一次,否则每个子串算该子串的\(endpos\)集合大小次. 用\(f[i]\)表示结点\(i\)表示的\(endpos\)集合大小,则\(f[i]\)为 ...
- BZOJ3998 TJOI2015弦论(后缀自动机)
先考虑相同子串视为一个.按SAM的拓扑序预处理出从每个节点开始能得到多少个本质不同子串(注意虽然一个节点对应多个子串,但到达该点时当前的子串显然是确定为其中一个的),然后按位贪心即可. 相同子串视为多 ...
- 【BZOJ3998】弦论(后缀自动机)
[BZOJ3998]弦论(后缀自动机) 题面 BZOJ 题解 这题应该很简单 构建出\(SAM\)后 求出每个点往后还能构建出几个串 按照拓扑序\(dp\)一些就好了 然后就是第\(k\)大,随便搞一 ...
随机推荐
- [CTSC2007]数据备份Backup 题解
题意: 一维直线上有n个点,任取2k个互不相同的点组成k条链,求链的最小总长 思路: 1.最优时链不相交,相邻两两相减,将题目转化为:在n-1个数中取互不相邻的k个数使总和最小. 2.贪心取最小的“数 ...
- [POJ3041] Asteroids(最小点覆盖-匈牙利算法)
传送门 题意: 给一个N*N的矩阵,有些格子有障碍,要求我们消除这些障碍,问每次消除一行或一列的障碍,最少要几次. 解析: 把每一行与每一列当做二分图两边的点. 某格子有障碍,则对应行与列连边. ...
- BZOJ2099: [Usaco2010 Dec]Letter 恐吓信
给两个长度不超过50000的串,A串可每次截连续一段复制出来,求最少复制几次能得到B串. 方法一:SAM.不会. 嗯好会了. #include<stdio.h> #include<s ...
- php之ThinkPHP的memcached类的修改
php之ThinkPHP的memcached类的修改 在Think\Cache\Driver\Memcached.class.php中,增加方法获取错误信息的方法,方便调试, public funct ...
- hdu3622 2-sat问题,二分+判断有无解即可。
/*2-sat问题初破!题意:每一对炸弹只能选一个(明显2-sat),每个炸弹半径自定,爆炸范围不可 相交,求那个最小半径的最大值(每种策略的最小半径不同).思:最优解:必然是选择的点最近 的俩个距离 ...
- POJ 2135 最小费用最大流 入门题
Farm Tour Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 19207 Accepted: 7441 Descri ...
- HDU 1024 Max Sum Plus Plus【DP,最大m子段和】
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1024 题意: 给定序列,给定m,求m个子段的最大和. 分析: 设dp[i][j]为以第j个元素结尾的 ...
- FATE---hdu2159(二重背包)
FATE Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- java内存区域和对象的产生
一直被java中内存组成弄的头晕眼花,这里总结下都有哪些,先上图片 程序计数器 小块内存,线程执行字节码的信号指示器,以此获取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复都要依赖他 ...
- GreenDao数据库的升级
应用使用了GreenDao数据库,在版本升级的时候需要更改dao的字段,新增.修改.删除字段操作,如果直接删除原来的表的话那用户原来的一些数据就没有了,所以在更新数据库的时候需要做一次封装,把原来的数 ...