借用罗穗骞论文中的讲解:

计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来。先将两个字符串连起来,中间用一个没有出现过的字符隔开。按height 值分组后,接下来的工作便是快速的统计每组中后缀之间的最长公共前缀之和。扫描一遍,每遇到一个B 的后缀就统计与前面的A 的后缀能产生多少个长度不小于k 的公共子串,这里A 的后缀需要用一个单调的栈来高效的维护。然后对A 也这样做一次。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cstdlib>
  6. using namespace std;
  7. const int N = 210008;
  8. typedef long long LL;
  9.  
  10. int val[N], sum[N], wa[N], wb[N];
  11. int sa[N], rk[N], height[N];
  12. char a[N], b[N];
  13.  
  14. inline bool cmp(int str[], int a, int b, int l){
  15. return str[a] == str[b] && str[a + l] == str[b + l];
  16. }
  17.  
  18. void da(char str[], int n, int m){
  19.  
  20. int *x = wa, *y = wb;
  21. memset(sum, 0, sizeof(sum));
  22.  
  23. for(int i = 0; i < n; i++){
  24. sum[x[i] = str[i]]++;
  25. }
  26. for(int i = 1; i < m; i++){
  27. sum[i] += sum[i - 1];
  28. }
  29. for(int i = n - 1; i >= 0; i--){
  30. sa[--sum[ x[i]] ] = i;
  31. }
  32. for(int j = 1, p = 1; p < n; j *= 2, m = p){
  33. p = 0;
  34. for(int i = n - j; i < n; i++){
  35. y[p++] = i;
  36. }
  37. for(int i = 0; i < n; i++){
  38. if(sa[i] >= j){
  39. y[p++] = sa[i] - j;
  40. }
  41. }
  42. for(int i = 0; i < n; i++){
  43. val[i] = x[ y[i] ];
  44. }
  45.  
  46. memset(sum , 0, sizeof(sum));
  47. for(int i = 0; i < n; i++){
  48. sum[val[i]]++;
  49. }
  50. for(int i = 1; i < m; i++){
  51. sum[i] += sum[i - 1];
  52. }
  53. for(int i = n - 1; i >= 0; i--){
  54. sa[--sum[ val[i] ]] = y[i];
  55. }
  56.  
  57. swap(x, y);
  58. x[sa[0]] = 0;
  59. p = 1;
  60. for(int i = 1 ; i < n; i++){
  61. x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1:p++;
  62. }
  63. }
  64. }
  65.  
  66. void getHeight(char str[], int n){
  67. for(int i = 1; i <= n; i++){
  68. rk[ sa[i] ] = i;
  69. }
  70. int k = 0;
  71. for(int i = 0; i < n; height[rk[i++]] = k){
  72. if(k) k--;
  73. int j = sa[rk[i] - 1];
  74. while(str[i + k] == str[j + k]){
  75. k++;
  76. }
  77. }
  78. }
  79.  
  80. struct node{
  81. int h;
  82. LL cnt;
  83. }stk[N];
  84.  
  85. int main(){
  86.  
  87. int k;
  88. while(~scanf("%d", &k) && k){
  89. scanf("%s %s", a, b);
  90. int n = strlen(a);
  91. int m = strlen(b);
  92. int len = n + m + 1;
  93. a[n] = 125;
  94. for(int i = n + 1, j = 0; j < m; i++, j++){
  95. a[i] = b[j];
  96. }
  97. a[len] = 0;
  98. da(a, len + 1, 150);
  99. getHeight(a, len);
  100. LL sum = 0;
  101. int top = 0;
  102. LL tot = 0;
  103. for(int i = 1; i <= len ; i++){
  104. int cnt = 0;
  105. if(height[i] < k){
  106. top = 0;
  107. tot = 0;
  108. }else{
  109. if(sa[i - 1] < n){
  110. cnt++;
  111. tot += height[i] - k + 1;
  112. }
  113. while(top > 0 && stk[top - 1].h > height[i]){
  114. top--;
  115. cnt += stk[top].cnt;
  116. tot -= (stk[top].h - height[i]) * stk[top].cnt;
  117. }
  118. stk[top].h = height[i];
  119. stk[top].cnt = cnt;
  120. top++;
  121. if(sa[i] > n){
  122. sum += tot;
  123. }
  124. }
  125. }
  126.  
  127. top = 0;
  128. tot = 0;
  129. for(int i = 1; i <= len ; i++){
  130. int cnt = 0;
  131. if(height[i] < k){
  132. top = 0;
  133. tot = 0;
  134.  
  135. }else{
  136. if(sa[i - 1] > n){
  137. cnt++;
  138. tot += height[i] - k + 1;
  139. }
  140. while(top > 0 && stk[top - 1].h > height[i]){
  141. top--;
  142. cnt += stk[top].cnt;
  143. tot -= (stk[top].h - height[i]) * stk[top].cnt;
  144. }
  145. stk[top].h = height[i];
  146. stk[top].cnt = cnt;
  147. top++;
  148. if(sa[i] < n){
  149. sum += tot;
  150. }
  151. }
  152. }
  153. printf("%I64d\n", sum);
  154. }
  155. return 0;
  156. }

  

POJ3415 Common Substrings(后缀数组 单调栈)的更多相关文章

  1. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

    题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K ...

  2. poj 3415 Common Substrings 后缀数组+单调栈

    题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...

  3. poj 3415 Common Substrings——后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...

  4. poj 3415 Common Substrings —— 后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...

  5. poj3415 Common Substrings (后缀数组+单调队列)

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9414   Accepted: 3123 Description A sub ...

  6. 【BZOJ-3238】差异 后缀数组 + 单调栈

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1561  Solved: 734[Submit][Status] ...

  7. BZOJ_3879_SvT_后缀数组+单调栈

    BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...

  8. BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈

    BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...

  9. BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)

    BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...

随机推荐

  1. Github GUI 托管代码教程

    附录:克隆仓库到本地:git clone https://github.com/chzeze/WeiboHomeCrawl.git

  2. MD5 加密字符串

    public class MD5 { /*** * MD5加码 生成32位md5码 */ public static String string2MD5(String inStr){ MessageD ...

  3. C#的is和as操作符来进行强制类型转换&&值类型的拆箱、装箱

    if(o is Employee) { Employee e=(Employee)o; //在if语句剩余的部分中使用e; } Employee e=o as Employee; if(e!=null ...

  4. Java中 final static super this instanceof 关键字用法

    一.final关键字 final可以修饰变量.方法及类: 1.当定义一个final变量时,jvm会将其分配到常量池中,其所修饰的对象只能赋值一次,对基本类型来说是其值不可变,引用类型(包括作为函数形参 ...

  5. java web 学习 --第十天(Java三级考试)

    第九天学习内容:http://www.cnblogs.com/tobecrazy/p/3470195.html 需求概述 创建程序模块,读取并显示数据库中的书籍信息.当前有如下需求:需要显示数据库中所 ...

  6. bind+dlz+mysql实现区域记录动态更新

    BIND-DLZ实验:http://bind-dlz.sourceforge.net/ 实验环境:RHEL4,BIND-9.5.0-P2.tar.gz(9.4.0以上版本都已含DLZ补丁),Mysql ...

  7. Centos6.5 SVN服务器 搭建及配置

    现有的项目开发中,版本控制机必不可少.合理的使用版本控制可以提高开发效果,在保证项目是最新的同时,也提高了源代码的安全性. 工具/原料 接入Internet的一台Centos6.5Linux计算机 安 ...

  8. 好用的php类库和方法

    1, /** * 将一个平面的二维数组按照指定的字段转换为树状结构 * * 用法: * @code php * $rows = array( * array('id' => 1, 'value' ...

  9. osg 纹理访问器

    #include<osgViewer/Viewer> #include<osg/Node>#include<osg/Geode>#include<osg/Gr ...

  10. SQL存储过程大全

    --增加 create proc usp_insertToText ), ), @usitPrice decimal as begin insert into TEST1 output inserte ...