题目链接

\(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代码,

算了学不来。。

  1. //126308kb 5512ms
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. const int N=1e6+3;
  6. struct Suffix_Automaton
  7. {
  8. int T,K,L,las,tot,fa[N],son[N][26],len[N],sz[N],right[N],A[N],tm[N];
  9. char s[N>>1];
  10. void Insert(int c)
  11. {
  12. int p=las,np=++tot; len[las=np]=len[p]+1;
  13. for(; p&&!son[p][c]; p=fa[p]) son[p][c]=np;
  14. if(!p) fa[np]=1;
  15. else
  16. {
  17. int q=son[p][c];
  18. if(len[q]==len[p]+1) fa[np]=q;
  19. else
  20. {
  21. int nq=++tot; len[nq]=len[p]+1;
  22. memcpy(son[nq],son[q],sizeof son[q]);
  23. fa[nq]=fa[q], fa[q]=fa[np]=nq;
  24. for(; son[p][c]==q; p=fa[p]) son[p][c]=nq;
  25. }
  26. }
  27. }
  28. void Build()
  29. {
  30. scanf("%s",s), las=tot=1, L=strlen(s);
  31. for(int i=0; i<L; ++i) Insert(s[i]-'a');
  32. for(int i=1; i<=tot; ++i) ++tm[len[i]];
  33. for(int i=1; i<=L; ++i) tm[i]+=tm[i-1];
  34. for(int i=1; i<=tot; ++i) A[tm[len[i]]--]=i;
  35. }
  36. void Query()
  37. {
  38. scanf("%d%d",&T,&K);
  39. if(!T) for(int i=1; i<=tot; ++i) sz[i]=right[i]=1;
  40. else
  41. {
  42. for(int p=1,i=0; i<L; ++i) ++right[p=son[p][s[i]-'a']];
  43. for(int i=tot,x=A[i]; i; x=A[--i]) right[fa[x]]+=right[x];//x not i!
  44. for(int i=1; i<=tot; ++i) sz[i]=right[i];
  45. }
  46. // sz[0]=sz[1]=0;
  47. for(int i=tot,x=A[i]; i; x=A[--i])
  48. for(int j=0; j<26; ++j) sz[x]+=sz[son[x][j]];
  49. if(K>sz[1]) {printf("-1"); return;}//其实并没有这种情况,要不输出-1就10分了233
  50. int p=1;
  51. while(K>0)
  52. {
  53. for(int i=0; i<26; ++i)
  54. if(son[p][i])//!...
  55. if(sz[son[p][i]]<K) K-=sz[son[p][i]];
  56. else{
  57. putchar(i+'a'), K-=right[p=son[p][i]];
  58. break;
  59. }
  60. }
  61. }
  62. }sam;
  63. int main()
  64. {
  65. sam.Build(), sam.Query();
  66. return 0;
  67. }

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. WEB前端技巧之JQuery为动态添加的元素绑定事件.md

      jquery 为动态添加的元素绑定事件 如果直接写click函数的话,只能把事件绑定在已经存在的元素上,不能绑定在动态添加的元素上 可以用delegate来实现 .delegate( select ...

  2. vue element-ui 实现点击查看审核记录

    <el-dialog title="审核信息" :visible.sync="seeVisible" width="30%" :bef ...

  3. 一致性哈希算法介绍,及java实现

    应用场景 在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法(Res ...

  4. jQuery下ajax事件的简单分析

    昨天写了一篇关于监视页面动态生成元素问题的文章,引起了一些小小的争议,不过我从中学到了很多.文章在这,<jQuery下实现等待指定元素加载完毕>当然 动态生成的节点元素 分很多种情况,这里 ...

  5. [原]JUnit 自定义扩展思路

    1. 理解Annotation,http://www.cnblogs.com/mandroid/archive/2011/07/18/2109829.html 2. JUNIT整体执行过程分析,htt ...

  6. 【GDOI2018】所有题目和解题报告

    使用说明:题意和数据范围都只是回忆内容,仅供参考.题解陆续补上. Day 1 第一题 题意:给定n个数字,要求划分成k的连续段使得每个连续段内的数字之和相同,求最大的k.n,Σai<=10^6. ...

  7. iOS 判断相册相机是否允许

    1 判断是否允许使用相机: NSString *mediaType = AVMediaTypeVideo; AVAuthorizationStatus authStatus = [AVCaptureD ...

  8. 针对Jigsaw勒索软件的解锁工具

    针对Jigsaw勒索软件的解锁工具 据了解, 用户的计算机系统一旦感染了勒索软件Jigsaw,如果用户没有在一个小时之内支付赎金(0.4个比特币,价值约为150美金),那么恶意软件将会把系统中的上千份 ...

  9. (windows下)安装mysql

    一.先从mysql的官网上下载对应版本的mysql zip包(适用于windows下的) 二.解压zip包放到自定义的文件夹下(我放的是e盘,路径为E:\mysql-5.6.40-winx64) 三. ...

  10. 一个查看Access数据库密码的工具

    一个可以查看Access数据库密码的工具AccessCracker.需要.net2.0环境支持. 网盘地址:https://pan.baidu.com/s/1btbsFcsKO0Enj-rjkTlz6 ...