题意:求一个串的字典序第k小的子串/本质不同第k小的子串。

解:一开始我的想法是在后缀树上找,但是不知道后缀树上的边对应的是哪些字符...

然而可以不用fail树转移,用转移边转移即可。

先建一个后缀自动机,记忆化搜索每个节点向后向后有多少个串。

然后从起点开始向后一个字符一个字符的确定。

注意每到一个新点就要判断是否结束,并把k减去在此结束的串的个数。

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. const int N = ;
  5.  
  6. int tr[N][], len[N], fail[N], siz[N], bin[N], cnt[N], topo[N];
  7. int top, last;
  8.  
  9. inline void init() {
  10. top = last = ;
  11. return;
  12. }
  13.  
  14. inline void insert(char c) {
  15. int f = c - 'a';
  16. int p = last, np = ++top;
  17. last = np;
  18. len[np] = len[p] + ;
  19. cnt[np] = ;
  20. while(p && !tr[p][f]) {
  21. tr[p][f] = np;
  22. p = fail[p];
  23. }
  24. if(!p) {
  25. fail[np] = ;
  26. }
  27. else {
  28. int Q = tr[p][f];
  29. if(len[Q] == len[p] + ) {
  30. fail[np] = Q;
  31. }
  32. else {
  33. int nQ = ++top;
  34. len[nQ] = len[p] + ;
  35. fail[nQ] = fail[Q];
  36. fail[Q] = fail[np] = nQ;
  37. memcpy(tr[nQ], tr[Q], sizeof(tr[Q]));
  38. while(tr[p][f] == Q) {
  39. tr[p][f] = nQ;
  40. p = fail[p];
  41. }
  42. }
  43. }
  44. return;
  45. }
  46.  
  47. inline void sort() {
  48. for(int i = ; i <= top; i++) {
  49. bin[len[i]]++;
  50. }
  51. for(int i = ; i <= top; i++) {
  52. bin[i] += bin[i - ];
  53. }
  54. for(int i = ; i <= top; i++) {
  55. topo[bin[len[i]]--] = i;
  56. }
  57. return;
  58. }
  59.  
  60. inline void count() {
  61. for(int i = top; i >= ; i--) {
  62. int x = topo[i];
  63. cnt[fail[x]] += cnt[x];
  64. }
  65. return;
  66. }
  67.  
  68. char s[N];
  69.  
  70. int DFS(int x) {
  71. if(siz[x]) {
  72. return siz[x];
  73. }
  74. siz[x] = cnt[x];
  75. for(int i = ; i < ; i++) {
  76. if(tr[x][i]) {
  77. siz[x] += DFS(tr[x][i]);
  78. }
  79. }
  80. return siz[x];
  81. }
  82.  
  83. int main() {
  84. scanf("%s", s + );
  85. int n = strlen(s + );
  86. init();
  87. for(int i = ; i <= n; i++) {
  88. insert(s[i]);
  89. }
  90. sort();
  91. int flag, k;
  92. scanf("%d%d", &flag, &k);
  93. if(flag) {
  94. count();
  95. }
  96. else {
  97. for(int i = ; i <= top; i++) {
  98. cnt[i] = ;
  99. }
  100. }
  101.  
  102. int sum = ;
  103. for(int i = ; i <= top; i++) {
  104. sum += cnt[i] * (len[i] - len[fail[i]]);
  105. }
  106.  
  107. int p = ;
  108. DFS(p);
  109. if(k > sum) {
  110. puts("-1");
  111. return ;
  112. }
  113. cnt[] = ;
  114. while() {
  115. //printf("k = %d %d \n", k, k == 1);
  116. if(k == ) {
  117. break;
  118. }
  119. else {
  120. k -= cnt[p];
  121. }
  122. //printf("k = %d p = %d \n", k, p);
  123. for(int i = ; i < ; i++) {
  124. if(!tr[p][i]) {
  125. continue;
  126. }
  127. if(siz[tr[p][i]] >= k) {
  128. putchar(i + 'a');
  129. p = tr[p][i];
  130. break;
  131. }
  132. else {
  133. k -= siz[tr[p][i]];
  134. }
  135. }
  136. }
  137.  
  138. return ;
  139. }

AC代码

又思考了一下,虽然记忆化搜索会搜到重复的节点,但是这些重复所表示的是到达它的不同方案,也就是它代表的不同子串。所以需要重复统计。

这样一个节点的一条转移边其实就是它下一个字符拼上f之后能形成的子串数。

感觉好神奇...

洛谷P3975 弦论的更多相关文章

  1. 洛谷 P3975 [TJOI2015]弦论 解题报告

    P3975 [TJOI2015]弦论 题目描述 为了提高智商,ZJY开始学习弦论.这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为\(n\)的字符串,求 ...

  2. 洛谷 P3975 / loj 2102 [TJOI2015] 弦论 题解【后缀自动机】【拓扑排序】

    后缀自动机入门. 题目描述 为了提高智商,ZJY 开始学习弦论. 这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为 \(n\) 的字符串,求出它的第 \ ...

  3. [洛谷P3975][TJOI2015]弦论

    题目大意:求一个字符串的第$k$大字串,$t$表示长得一样位置不同的字串是否算多个 题解:$SAM$,先求出每个位置可以到达多少个字串($Right$数组),然后在转移图上$DP$,若$t=1$,初始 ...

  4. 【洛谷 P3975】 [TJOI2015]弦论(后缀自动机)

    题目链接 建出后缀自动机. T=0,每个子串算一次,否则每个子串算该子串的\(endpos\)集合大小次. 用\(f[i]\)表示结点\(i\)表示的\(endpos\)集合大小,则\(f[i]\)为 ...

  5. 洛谷P3975 跳房子 [DP,单调队列优化,二分答案]

    题目传送门 跳房子 题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一. 跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 n 个格子,这些格子都在同一 ...

  6. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  7. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  8. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

  9. 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

随机推荐

  1. 【译】Focused and Diffuse Modes(专注与发散模式)

    Focused and Diffuse Modes ---文章来源:coursera 面对一个问题,当无论如何都想不出办法时,你会怎么做呢?对于僵尸们来说,只需简单地不断用脑袋撞墙即可.然而活生生的大 ...

  2. E: Unable to correct problems, you have held broken packages

    问题: apt install libmysqlclient-dev Reading package lists... DoneBuilding dependency tree       Readi ...

  3. OSError: mysql_config not found

    使用Python3开发一个管理平台,用MySQL数据库存放元数据.使用pip安装mysqlclient模块时出现“OSError: mysql_config not found”错误. 解决: # a ...

  4. python functools.wraps functools.partial实例解析

    一:python functools.wraps 实例 1. 未使用wraps的实例 #!/usr/bin/env python # coding:utf-8 def logged(func): de ...

  5. DBExpress动态连接SQL-Server

    procedure TForm1.Button1Click(Sender: TObject);var  theCNN : TSQLConnection;//定义连接,要引用 DB, SqlExprbe ...

  6. Spring Boot 构建电商基础秒杀项目 (一) 项目搭建

    SpringBoot构建电商基础秒杀项目 学习笔记 Spring Boot 其实不是什么新的框架,它默认配置了很多框架的使用方式,就像 maven 整合了所有的 jar 包, Spring Boot ...

  7. React 学习(七) ---- create-react-app

    现在react 基础知识已经算是学完了,知道了React是做什么的,以及怎么使用,是时候学习一个webpack, babel 等现代化前端开发了,真正做项目的时候,我们不可能再使用babel 的线上编 ...

  8. micro-fusion & macro-fusion

    micro-fusion 随着技术的发展,CPU内部指令处理单元(execution unit)以及端口(port)增多,在Pentium 4的时候,发出到Execution Unit的μops的th ...

  9. No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK问题解决

    Maven构建项目报错: 解决办法: 1.eclipse菜单 -  Window - Preferences- Java - Installed JREs 将配置的JRE定位到JDK,例如JRE ho ...

  10. Linux编译静态库与共享库

    静态库: cc  -c   mod1.c  mod2.c //编译 ar   r     libdemo.a   mod1.o   mod2.o //生成静态库 cc  -c   prog.c //编 ...