大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置.

这是一篇很好的题解:

https://blog.csdn.net/sdauguanweihong/article/details/100063096

加点个人:

我对上面的题解更为详细的解释下:

后缀数组处理出来的heigth[] 数组 有个这样的性质:

对于排名 a 的后缀字符串 与排名 b 的后缀字符串  ,他们的最长公共前缀的长度为 min{heigth[a+1],heigth[a+2],heigth[b]};

依据这样的性质就可以二分线段树出[l,r] 这个字符串 是在多少排名的区间[L,R]了;

注意:我本想贪图方便用先二分l然后判断[l,pos] 的最小值复杂度为log*log  这个会T的

所以找这个区间要用log的方法,就是在存了最小值的线段树里面去搜左孩子啊右孩子什么的

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define INF 0x3f3f3f3f
  4. const int maxn = ;
  5. char s[maxn];
  6. int y[maxn],x[maxn],c[maxn],sa[maxn],rk[maxn],height[maxn],wt[];
  7. int n,k,q;
  8.  
  9. int get_SA(int m){
  10. for(int i= ; i<=m ; i++) c[i]=;
  11. for(int i= ; i<=n ; i++) sa[i]=;
  12. for(int i= ; i<=n ; i++) ++c[x[i]=s[i]];
  13. for(int i= ; i<=m ; i++) c[i]+=c[i-];
  14. for(int i=n ; i>= ; i--) sa[c[x[i]]--]=i;
  15. for(int k= ; k<=n ; k<<=){
  16. int num=;
  17. for(int i=n-k+ ; i<=n ; i++) y[++num]=i;
  18. for(int i= ; i<=n ; i++) if(sa[i]>k) y[++num]=sa[i]-k;
  19. for(int i= ; i<=m ; i++) c[i]=;
  20. for(int i= ; i<=n ; i++) ++c[x[i]];
  21. for(int i= ; i<=m ; i++) c[i]+=c[i-];
  22. for(int i=n ; i>= ; i--) sa[c[x[y[i]]]--]=y[i],y[i]=;
  23. swap(x,y);
  24. x[sa[]]=;
  25. num=;
  26. for(int i= ; i<=n ; i++)
  27. x[sa[i]]=(y[sa[i]]==y[sa[i-]] && y[sa[i]+k]==y[sa[i-]+k]) ? num : ++num;
  28. if (num==n) break;
  29. m=num;
  30. }
  31. }
  32. int get_height() {
  33. int k=;
  34. for (int i=; i<=n; ++i) rk[sa[i]]=i;
  35. for (int i=; i<=n; ++i) {
  36. if (rk[i]==) continue;
  37. if (k) --k;
  38. int j=sa[rk[i]-];
  39. while (j+k<=n && i+k<=n && s[i+k]==s[j+k]) ++k;
  40. height[rk[i]]=k;
  41. }
  42. }
  43.  
  44. int mi[maxn<<];
  45. void pushup(int rt){
  46. mi[rt]=min(mi[rt<<],mi[rt<<|]);
  47. }
  48. void build(int l,int r,int rt)
  49. {
  50. if ( l==r )
  51. {
  52. mi[rt]=height[l];
  53. return ;
  54. }
  55. int m = (l+r) >> ;
  56. build(l,m,rt<<);
  57. build(m+,r,rt<<|);
  58. pushup(rt);
  59. }
  60.  
  61. int solvel(int o , int l , int r , int x , int v){
  62. int mid=(l+r)>>;
  63. if(r<=x){
  64. if(l==r) return mi[o]>=v?l:-;
  65. if(mi[o<<|]<v) return solvel(o<<|,mid+,r,x,v);
  66. int t=solvel(o<<,l,mid,x,v);
  67. return t==-?mid+:t;
  68. }
  69. if(mid>=x) return solvel(o<<,l,mid,x,v);
  70. int R=solvel(o<<|,mid+,r,x,v);
  71. if (R==-||R>mid+) return R;
  72. int L = solvel(o<<,l,mid,x,v);
  73. return L==-?R:L;
  74. }
  75.  
  76. int solver(int o, int l, int r, int x, int v){
  77. int mid=(l+r)>>;
  78. if (x<=l) {
  79. if (l==r) return mi[o]>=v?l:-;
  80. if (mi[o<<]<v) return solver(o<<,l,mid,x,v);
  81. int t = solver(o<<|,mid+,r,x,v);
  82. return t==-?mid:t;
  83. }
  84. if (mid<x) return solver(o<<|,mid+,r,x,v);
  85. int L = solver(o<<,l,mid,x,v);
  86. if (L==-||L<mid) return L;
  87. int R = solver(o<<|,mid+,r,x,v);
  88. return R==-?L:R;
  89. }
  90.  
  91. int tot;
  92. int lson[maxn<<],rson[maxn<<],T[maxn],cc[maxn<<];
  93. void zhu_build(int &root,int l,int r)
  94. {
  95. root=++tot;
  96. if ( l==r ) return;
  97. int mid=(l+r)/;
  98. zhu_build(lson[root],l,mid);
  99. zhu_build(rson[root],mid+,r);
  100. }
  101. void update(int root,int &rt,int p,int val,int l,int r)
  102. {
  103. rt=++tot;
  104. lson[rt]=lson[root],rson[rt]=rson[root];
  105. cc[rt]=cc[root]+val;
  106. if ( l==r ) return;
  107. int mid=(l+r)/;
  108. if ( p<=mid ) update(lson[rt],lson[rt],p,val,l,mid);
  109. else update(rson[rt],rson[rt],p,val,mid+,r);
  110. }
  111. int query(int rt_,int rt,int l,int r,int k)
  112. {
  113. if ( l==r ) return l;
  114. int mid=(l+r)/;
  115. int sum=cc[lson[rt_]]-cc[lson[rt]];
  116. if ( sum>=k ) return query(lson[rt_],lson[rt],l,mid,k);
  117. else return query(rson[rt_],rson[rt],mid+,r,k-sum);
  118. }
  119.  
  120. int main(){
  121. int _;scanf("%d",&_);
  122. while(_--){
  123. scanf("%d%d%s",&n,&q,s+);
  124.  
  125. get_SA();
  126.  
  127. get_height();
  128. build(,n,);
  129. tot=;
  130. zhu_build(T[],,n);
  131. for(int i= ; i<=n ; i++){
  132. update(T[i-],T[i],sa[i],,,n);
  133.  
  134. }
  135. while(q--){
  136. int l,r;scanf("%d%d%d",&l,&r,&k);
  137. int p=rk[l];
  138. int ql = p>?solvel(,,n,p,r-l+)-:;
  139. int qr = p<n?solver(,,n,p+,r-l+):n;
  140. if (ql<) ql = p;
  141. if (qr<) qr = p;
  142. int ans;
  143. if(qr-ql+<k)
  144. ans=-;
  145. else
  146. ans=query(T[qr],T[ql-],,n,k);
  147.  
  148. printf("%d\n",ans);
  149. }
  150. }
  151. }

K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)的更多相关文章

  1. HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...

  2. [CSP-S模拟测试]:platform(后缀数组+二分+线段树)

    题目传送门 题目描述 走过奈何桥有一个名叫望乡台的土台,望乡台有个名曰孟婆的老妇人在卖孟婆汤.一生爱恨情仇,一世浮沉得失,都可以随这碗孟婆汤遗忘得干干净净.现在有$n$碗孟婆汤摆成一排,汤的品种不超过 ...

  3. HDU 5558 后缀数组+二分

    题意有一些绕,但其实就是对于不断变化的i,求以j(0=j<i)使得suffix[j]与suffix[i]的最长公共前缀最长,如果有多个j,则取最小的j. 可以在rank数组中二分,在1-rank ...

  4. UVA-11107 Life Forms(求出现K次的子串,后缀数组+二分答案)

    题解: 题意: 输入n个DNA序列,你的任务是求出一个长度最大的字符串,使得它在超过一半的DNA序列中出现.如果有多解,按照字典序从小到大输入所有解. 把n个DNA序列拼在一起,中间用没有出现过的字符 ...

  5. BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )

    二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...

  6. hdu 3948 后缀数组

    The Number of Palindromes Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (J ...

  7. 【bzoj4310】跳蚤 后缀数组+二分

    题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...

  8. BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)

    题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...

  9. POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)

    洛谷P2743传送门 题目大意:给你一个序列,求其中最长的一对相似等长子串 一对合法的相似子串被定义为: 1.任意一个子串长度都大于等于5 2.不能有重叠部分 3.其中一个子串可以在全部+/-某个值后 ...

随机推荐

  1. Linear Discriminant Analysis

    Suppose that we model each class density as multivariate Gaussian, in practice we do not know the pa ...

  2. [LeetCode] 210. 课程表 II

    题目链接:https://leetcode-cn.com/problems/course-schedule-ii/ 题目描述: 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前 ...

  3. Java8与JDK8和JDK1.8有什么区别?

    JDK版本与发行时间 版本 名称 发行日期 JDK 1.0 Oak(橡树) 1996-01-23 JDK 1.1 none(无) 1997-02-19 JDK 1.1.4 Sparkler(宝石) 1 ...

  4. Lucene整理--中文分词

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/hai_cheng001/article/details/37511379 看lucene主页(htt ...

  5. vue项目引入外部字体

    1.UI设计图有"华文黑体",担心客户端没有该字体,将"huawen.ttf"字体文件,放入项目中: 2.创建一个font.scss(或font.css)文件: ...

  6. netperf编译./configure时报错 "error: cannot guess build type;you nust specify one"

    问题: 解决办法-亲测可用: 尝试:./configure --build=mingw提示无法辨别 checking build system type... Invalid configuratio ...

  7. mpg123 - 播放 MPEG 1.0/2.0 Layer-1, -2, -3 音频文件

    语法 mpg123 [ -tscvqy01m24 ][ -b size ][ -k num ][ -n num ][ -f factor ][ -r rate ][ -g gain ][ -a dev ...

  8. Linux架构--------Rsync守护进程推和拉

    一.Rsync基本概述 rsync是一款开源.快速.多功能.可实现全量及增量的本地或远程数据同步备份的优秀工具.rsync软件适用于Unix/linux/Windows等多种操作系统平台. 二.Rsy ...

  9. Vscode添加谷歌Debug插件

    1. 2.安装好 Debugger for Chrome之后,找到要进行Debug的文件 3. 4.进入到launch.json文件中进行相应的配置 配置文件内容如下: { "version ...

  10. POJ 1966 Cable TV Network (最大流最小割)

    $ POJ~1966~Cable~TV~Network $ $ solution: $ 第一眼可能让人很难下手,但本就是冲着网络流来的,所以我们直接一点.这道题我们要让这个联通图断开,那么势必会有两个 ...