BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串
http://www.lydsy.com/JudgeOnline/problem.php?id=3998
后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串为前缀的字符串数量和某字符串的出现数量。
wa了两次,写题时犯得错误有:
1.使用样例检查出来向下搜索字符串时没有减去字符串本身出现的数量,比如样例中aabc 0 3,不计重复的情况下向下搜索还要多减一下a和aa分别出现的1次;
2.第一次wa检查出来val没有在建自动机的时候赋值,所以T=1的时候val和g都=0;
3.第二次wa检查半天自己随便打了个字符串跑一下发现数量不对,然后找了半天最后看出来是自己的ac自动机写错了一个len的赋值,太zz了orz。
还是要熟悉一下自动机的写法。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=;
int siz,T;
long long K;
char ch[maxn*]={};
int cnt[maxn*]={};//按照深度排序
int b[maxn*]={};//排序后每个的rk
long long val[maxn*]={};//每个状态出现的数目
long long g[maxn*]={};//每个状态及其所有以其为前缀后继的数目
struct nod{
int sig[];
int f,len;
void cle(){f=-;len=;memset(sig,-,sizeof(sig));}
}t[maxn*];
int las=,tot=;
void add(int z){
int x=++tot; t[x].cle();
t[x].len=t[las].len+;
val[x]=;
int i=las;
for(;i!=-&&t[i].sig[z]==-;i=t[i].f)
t[i].sig[z]=x;
if(i==-)t[x].f=;
else{
int p=t[i].sig[z];
if(t[p].len==t[i].len+)t[x].f=p;
else{
int y=++tot;t[y].cle();
t[y]=t[p];
t[y].len=t[i].len+;
t[x].f=t[p].f=y;
for(;i!=-&&t[i].sig[z]==p;i=t[i].f)
t[i].sig[z]=y;
}
}las=x;
}
void pai(){
for(int i=;i<=tot;i++)++cnt[t[i].len];
for(int i=;i<=siz;i++)if(i)cnt[i]+=cnt[i-];
for(int i=;i<=tot;i++)b[cnt[t[i].len]--]=i;
}
void doit(){
for(int i=tot+;i;i--){
int z=b[i];
if(T&&z)val[t[z].f]+=val[z];
else val[z]=;
}
val[]=;
for(int i=tot+;i;i--){
int z=b[i];
g[z]=val[z];
for(int j=;j<;j++)if(t[z].sig[j]!=-)g[z]+=g[t[z].sig[j]];
}
}
void getit(int x,long long k){
if(k<)return;
long long sum=;
for(int i=;i<;i++){
if(!t[x].sig[i])continue;
if(sum<k&&sum+g[t[x].sig[i]]>=k){
printf("%c",'a'+i);
getit(t[x].sig[i],k-sum-val[t[x].sig[i]]);
break;
}sum+=g[t[x].sig[i]];
}
}
int main(){
t[].cle();
scanf("%s",ch);siz=strlen(ch);
for(int i=;i<siz;i++)add(int(ch[i]-'a'));
pai();
scanf("%d%lld",&T,&K);
doit();
if(K>g[])printf("-1\n");
else getit(,(long long)K);
return ;
}
BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串的更多相关文章
- BZOJ 3998 TJOI2015 弦论 后缀自动机+DAG上的dp
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3998 题意概述:对于一个给定长度为N的字符串,求它的第K小子串是什么,T为0则表示不同位置 ...
- BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]
3998: [TJOI2015]弦论 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2152 Solved: 716[Submit][Status] ...
- BZOJ 3998 [TJOI2015]弦论 ——后缀自动机
直接构建后缀自动机. 然后. 然后只需要再后缀自动机的go树上类似二分的方法进行查找即可,实际上是“26分”. 然后遇到了处理right集合的问题,然后觉得在go和parent树上上传都是可以的,毕竟 ...
- bzoj 3998 [TJOI2015]弦论——后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3998 相同子串算多个的话,先求好 right ,然后求一个 sm 表示走到这个点之后有几种走 ...
- BZOJ.3998.[TJOI2015]弦论(后缀自动机)
题目链接 \(Description\) 给定字符串S,求其第K小子串.(若T=0,不同位置的相同子串算1个:否则算作多个) \(Solution\) 建SAM,处理出对于每个节点,它和它的所有后继包 ...
- BZOJ 3998: [TJOI2015]弦论(后缀自动机)
传送门 解题思路 \(T=0\)时就和SP7258一样,\(T=1\)时其实也差不多,只不过要把每个点原来是\(1\)的权值改为\(Right\)集合的大小. 代码 #include<iostr ...
- ●BZOJ 3998 [TJOI2015]弦论
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3998题解: 后缀自动机. 当T=0时, 由于在后缀自动机上沿着trans转移,每个串都是互不 ...
- bzoj 3998: [TJOI2015]弦论【SA+二分||SAM】
SA的话t==0直接预处理出每个后缀的不同串贡献二分即可,然后t==1就按字典序枚举后缀,然后跳右端点计算和当前后缀的前缀相同的子串个数,直到第k个 不过bzoj上会T #include<ios ...
- bzoj 3998: [TJOI2015]弦论
Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...
随机推荐
- 【CodeForces】947 D. Picking Strings
[题目]D. Picking Strings [题意]给定只含'A','B','C'的字符串,支持以下变换:1.A - BC 2.B - AC 3.C - AB 4.AAA - empty ...
- 【VIJOS】P1512 SuperBrother打鼹鼠
[算法]二维树状数组 [题解] 1.树状数组尽量不要出现0,因此所有坐标+1 2.面积求法(默认1开始):(x1,y1)(x2,y2)=sum(x2,y2)-sum(x1-1,y2)-sum(x2,y ...
- web上下文监听器ServletContextListener
1 package com.liveyc.common.listener; import javax.servlet.ServletContextEvent; import javax.servlet ...
- Tomcat面试题目
1.tomcat给你你怎样去调优? 1. JVM参数调优:-Xms<size> 表示JVM初始化堆的大小,-Xmx<size>表示JVM堆的最大值.这两个值的大小一般根据需要进 ...
- php文件上传——php经典实例
php文件上传——php经典实例 表单页 <html> <head> <title>文件上传</title> <meta charset='ut ...
- Tinyos Makerules解读
Makerules 文件解读 位于/opt/tinyos-2.1.2/support/make #-*-Makefile-*- vim:syntax=make #$Id: Makerules,v 1. ...
- INIT_WORK
借助runtime pm,在需要使用模块时,增加引用计数(可调用pm_runtime_get),不需要使用时,减少引用计数(可调用pm_runtime_put). 1.INIT_WORK(struct ...
- PostGIS 操作geometry方法
WKT定义几何对象格式: POINT(0 0) ——点 LINESTRING(0 0,1 1,1 2) ——线 POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2 ...
- 使用非root用户启动tomcat
以下操作均为以root用户运行1.添加tomcat用户组 /usr/sbin/groupadd tomcat 2.添加tomcat用户,并限制登录 /usr/sbin/useradd -s /bin/ ...
- Ps钢笔操作技巧
鼠标左键单击=新建锚点:Ctrl+鼠标左键=移动锚点/移动调节点: Alt+鼠标左键=锚点/角点转换: 方向键=微调锚点位置: shift+鼠标左键=新建水平/垂直锚点:Ctrl+Alt+鼠标左键=选 ...