题目链接

\(Description\)

给定字符串S,求其第K小子串。(若T=0,不同位置的相同子串算1个;否则算作多个)

\(Solution\)

建SAM,处理出对于每个节点,它和它的所有后继包含的子串数量sz(自叶子向根枚举转移更新即可),然后在SAM上走。

每次优先看字典序小的边(设会到达v),若sz[v]<K,则K-=sz[v],枚举下一条边;否则K-=A[v],输出这个转移,然后p=v。(是A[v]!是匹配了v节点)

如果T=0,更新时sz[p]的初值为1,A[p]=1;如果T=1,那么更新时sz[p]的初值为|right[p]|,A[p]=|right[p]|。

right的求法:按原串在SAM上走一遍,更新经过点的right,然后自parent树底向上合并给fa的right就可以了。

感觉理解有个误区。。虽然一个节点是会代表多个串,但是。。你从一个状态走来并不是说匹配了这个点代表的所有串。所以就sz[]=1 or |right|。以后再匹配上别的点自然会加。

重新想了下好像之前理解的没错。。→_→

每个状态s代表的所有串在原串中的出现次数和每次出现的右端点相同。

表示很服Rank1.

到处找找到了他的SAM代码,

算了学不来。。

//126308kb	5512ms
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=1e6+3; struct Suffix_Automaton
{
int T,K,L,las,tot,fa[N],son[N][26],len[N],sz[N],right[N],A[N],tm[N];
char s[N>>1];
void Insert(int c)
{
int p=las,np=++tot; len[las=np]=len[p]+1;
for(; p&&!son[p][c]; p=fa[p]) son[p][c]=np;
if(!p) fa[np]=1;
else
{
int q=son[p][c];
if(len[q]==len[p]+1) fa[np]=q;
else
{
int nq=++tot; len[nq]=len[p]+1;
memcpy(son[nq],son[q],sizeof son[q]);
fa[nq]=fa[q], fa[q]=fa[np]=nq;
for(; son[p][c]==q; p=fa[p]) son[p][c]=nq;
}
}
}
void Build()
{
scanf("%s",s), las=tot=1, L=strlen(s);
for(int i=0; i<L; ++i) Insert(s[i]-'a');
for(int i=1; i<=tot; ++i) ++tm[len[i]];
for(int i=1; i<=L; ++i) tm[i]+=tm[i-1];
for(int i=1; i<=tot; ++i) A[tm[len[i]]--]=i;
}
void Query()
{
scanf("%d%d",&T,&K);
if(!T) for(int i=1; i<=tot; ++i) sz[i]=right[i]=1;
else
{
for(int p=1,i=0; i<L; ++i) ++right[p=son[p][s[i]-'a']];
for(int i=tot,x=A[i]; i; x=A[--i]) right[fa[x]]+=right[x];//x not i!
for(int i=1; i<=tot; ++i) sz[i]=right[i];
}
// sz[0]=sz[1]=0;
for(int i=tot,x=A[i]; i; x=A[--i])
for(int j=0; j<26; ++j) sz[x]+=sz[son[x][j]];
if(K>sz[1]) {printf("-1"); return;}//其实并没有这种情况,要不输出-1就10分了233
int p=1;
while(K>0)
{
for(int i=0; i<26; ++i)
if(son[p][i])//!...
if(sz[son[p][i]]<K) K-=sz[son[p][i]];
else{
putchar(i+'a'), K-=right[p=son[p][i]];
break;
}
}
}
}sam; int main()
{
sam.Build(), sam.Query();
return 0;
}

BZOJ.3998.[TJOI2015]弦论(后缀自动机)的更多相关文章

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

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

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

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

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

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

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

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

  5. bzoj 3998 [TJOI2015]弦论——后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3998 相同子串算多个的话,先求好 right ,然后求一个 sm 表示走到这个点之后有几种走 ...

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

    传送门 解题思路 \(T=0\)时就和SP7258一样,\(T=1\)时其实也差不多,只不过要把每个点原来是\(1\)的权值改为\(Right\)集合的大小. 代码 #include<iostr ...

  7. ●BZOJ 3998 [TJOI2015]弦论

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3998题解: 后缀自动机. 当T=0时, 由于在后缀自动机上沿着trans转移,每个串都是互不 ...

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

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

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

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

随机推荐

  1. PHP扩展开发--编写一个helloWorld扩展

    为什么要用C扩展 C是静态编译的,执行效率比PHP代码高很多.同样的运算代码,使用C来开发,性能会比PHP要提升数百倍. 另外C扩展是在进程启动时加载的,PHP代码只能操作Request生命周期的数据 ...

  2. 以后的博客将更新到自己的域名pythonsite.com,欢迎访问

    以后的博客将更新到自己的域名pythonsite.com,欢迎访问

  3. tensorboard遇到的坑

    <ul><li>No graph definition files were found.</li></ul> <p>启动命令 tensor ...

  4. linux笔记_day09

    1.运算器.控制器.存储器.输入输出(IO) 地址总线:内存寻址 数据总线:传输数据 控制总线:控制指令 寄存器:cpu暂时存储器 2.系统设定 默认输出设备:标准输出,STDOUT,1(描述符)(显 ...

  5. 八、mini2440裸机程序之UART(2)UART0与PC串口通信【转】

    转自:http://blog.csdn.net/shengnan_wu/article/details/8309417 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.相关原理图 2.相关寄 ...

  6. 从xtrabackup备份恢复单表【转】

    目前对MySQL比较流行的备份方式有两种,一种上是使用自带的mysqldump,另一种是xtrabackup,对于数据时大的环境,普遍使用了xtrabackup+binlog进行全量或者增量备份,那么 ...

  7. WPF中各个Template的分析(转)

    作为新手,还是没看明白本文,留着以后再学习 在使用TabControl.ListView.Menu.TreeView的时候被各种Template搞得头昏眼花,决心把这个问题搞清楚,究竟什么时候该用什么 ...

  8. pyqt5-组件

    组件(widgets)是构建一个应用的基础模块.PyQt5有广泛的各式各样的组件,包含:复选按钮(QCheckBox),切换按钮(ToggleButton),滑块条(QSlider),进度条(Prog ...

  9. CF601A 【The Two Routes】

    看数据范围,然后果断邻接矩阵$Floyd$啊 对于公路和铁路,各建一个图,分别跑最短路,然后取最大值即可 #include<iostream> #include<cstdio> ...

  10. vim 如何与外界粘贴复制

    在学习使用vim 的过程序,我们知道在vim 里面,粘贴复制的命令是y/p ,但是我们总会碰到这样的问题:如何把vim 里面复制的内容粘贴到vim 之外或者把vim 外面复制的内容粘贴到vim 里面? ...