题目链接:https://vjudge.net/problem/POJ-3415

Common Substrings
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 12240   Accepted: 4144

Description

A substring of a string T is defined as:

T(ik)=TiTi+1...Ti+k-1, 1≤ii+k-1≤|T|.

Given two strings AB and one integer K, we define S, a set of triples (ijk):

S = {(ijk) | kKA(ik)=B(jk)}.

You are to give the value of |S| for specific AB and K.

Input

The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=0.

1 ≤ |A|, |B| ≤ 105
1 ≤ K ≤ min{|A|, |B|}
Characters of A and B are all Latin letters.

Output

For each case, output an integer |S|.

Sample Input

  1. 2
  2. aababaa
  3. abaabaa
  4. 1
  5. xx
  6. xx
  7. 0

Sample Output

  1. 22
  2. 5

Source

题意:

给出两个字符串,求有多少对长度不小于k的公共子串,子串相同但位置不同也单独算作一对。

题解:

1.将两个字符串拼接在一起,中间用分隔符隔开,得到新串。并且需要记录每个位置上的字符(后缀)属于哪一个字符串。

2.求出新串的后缀数组。可知sa[i]和sa[j]的最长公共前缀为:min(height[k])i+1<=k<=j。

3.根据第二点,可以枚举sa数组,当遇到A串时,就先放着,当遇到B串时,就往前统计与所有A串的最长公共前缀,假如为len,那么就能增加len-k+1个公共前缀了。由于是按着sa的顺序枚举下去的,所以对于在B串下面的A串是没有统计到的,所以需要二次统计:把A串当成B串, B串当成A串,然后再进行统计,方可无遗漏。

4.往前统计时需要用到单调栈。

代码如下:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <vector>
  6. #include <cmath>
  7. #include <queue>
  8. #include <stack>
  9. #include <map>
  10. #include <string>
  11. #include <set>
  12. using namespace std;
  13. typedef long long LL;
  14. const int INF = 2e9;
  15. const LL LNF = 9e18;
  16. const int MOD = 1e9+;
  17. const int MAXN = 2e5+;
  18.  
  19. int id[MAXN];
  20. int r[MAXN], sa[MAXN], Rank[MAXN], height[MAXN];
  21. int t1[MAXN], t2[MAXN], c[MAXN];
  22.  
  23. bool cmp(int *r, int a, int b, int l)
  24. {
  25. return r[a]==r[b] && r[a+l]==r[b+l];
  26. }
  27.  
  28. void DA(int str[], int sa[], int Rank[], int height[], int n, int m)
  29. {
  30. n++;
  31. int i, j, p, *x = t1, *y = t2;
  32. for(i = ; i<m; i++) c[i] = ;
  33. for(i = ; i<n; i++) c[x[i] = str[i]]++;
  34. for(i = ; i<m; i++) c[i] += c[i-];
  35. for(i = n-; i>=; i--) sa[--c[x[i]]] = i;
  36. for(j = ; j<=n; j <<= )
  37. {
  38. p = ;
  39. for(i = n-j; i<n; i++) y[p++] = i;
  40. for(i = ; i<n; i++) if(sa[i]>=j) y[p++] = sa[i]-j;
  41.  
  42. for(i = ; i<m; i++) c[i] = ;
  43. for(i = ; i<n; i++) c[x[y[i]]]++;
  44. for(i = ; i<m; i++) c[i] += c[i-];
  45. for(i = n-; i>=; i--) sa[--c[x[y[i]]]] = y[i];
  46.  
  47. swap(x, y);
  48. p = ; x[sa[]] = ;
  49. for(i = ; i<n; i++)
  50. x[sa[i]] = cmp(y, sa[i-], sa[i], j)?p-:p++;
  51.  
  52. if(p>=n) break;
  53. m = p;
  54. }
  55.  
  56. int k = ;
  57. n--;
  58. for(i = ; i<=n; i++) Rank[sa[i]] = i;
  59. for(i = ; i<n; i++)
  60. {
  61. if(k) k--;
  62. j = sa[Rank[i]-];
  63. while(str[i+k]==str[j+k]) k++;
  64. height[Rank[i]] = k;
  65. }
  66. }
  67.  
  68. int Stack[MAXN][], top;
  69. LL cal(int k, int len, int flag)
  70. {
  71. LL sum = , tmp = ;
  72. top = ;
  73. for(int i = ; i<=len; i++)
  74. {
  75. if(height[i]<k)
  76. tmp = top = ;
  77. else
  78. {
  79. int cnt = ;
  80. if(id[sa[i-]]==flag)
  81. tmp += height[i]-k+, cnt++;
  82. while(top> && height[i]<=Stack[top-][])
  83. {
  84. tmp -= 1LL*Stack[top-][]*(Stack[top-][]-height[i]);
  85. cnt += Stack[top-][];
  86. top--;
  87. }
  88. Stack[top][] = height[i];
  89. Stack[top++][] = cnt;
  90. if(id[sa[i]]!=flag)
  91. sum += tmp;
  92. }
  93. }
  94. return sum;
  95. }
  96.  
  97. char str[MAXN];
  98. int main()
  99. {
  100. int k;
  101. while(scanf("%d",&k)&&k)
  102. {
  103. int len = ;
  104. scanf("%s", str);
  105. int LEN = strlen(str);
  106. for(int j = ; j<LEN; j++)
  107. {
  108. r[len] = str[j];
  109. id[len++] = ;
  110. }
  111. r[len] = '$';
  112. id[len++] = ;
  113. scanf("%s", str);
  114. LEN = strlen(str);
  115. for(int j = ; j<LEN; j++)
  116. {
  117. r[len] = str[j];
  118. id[len++] = ;
  119. }
  120. r[len] = ;
  121. DA(r,sa,Rank,height,len,);
  122. cout<< cal(k,len,)+cal(k,len,) <<endl;
  123. }
  124. }

POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数的更多相关文章

  1. POJ3415 Common Substrings(后缀数组 单调栈)

    借用罗穗骞论文中的讲解: 计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来.先将两个字符串连起来,中间用一个没有出现过的字符隔开.按height ...

  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. SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数

    题目链接:https://vjudge.net/problem/SPOJ-SUBST1 SUBST1 - New Distinct Substrings #suffix-array-8 Given a ...

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

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

  8. BZOJ_3879_SvT_后缀数组+单调栈

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

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

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

随机推荐

  1. Ajax学习(一)——与Ajax的初次相识

        AJAX是"Asynchronous Javascript And XML"的缩写,从字面上解释是"异步JavaScript和XML"的简称. 它不是一 ...

  2. 常见函数strlen、strcmp、strstr原型实现

    数组元素的结束符为'\0'.串的结束符为NULL 一.strlen #include <iostream> using namespace std; long h_strlen(const ...

  3. dom控制

    (1)创建新节点 createDocumentFragment()    //创建一个DOM片段 createElement_x_x()   //创建一个具体的元素 createTextNode()  ...

  4. C#获取webbrowser完整cookie

    [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] //API设定Cookie stat ...

  5. 跟我学AngularJs:Controller数据共享、继承、通信使用具体解释

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主讲了AngularJs中的Controller中数据共享.继承.通信的具体使用 本 ...

  6. php程序执行过程--非宏观和微观而是写的程序一行一行的路径----利用xdebug了解一段程序的执行过程----覆盖率

    1.xdebug_start_code_coverage();//在需要开始跟踪程序执行路径时使用 2.var_dump(xdebug_get_code_coverage());//在结尾使用打印程序 ...

  7. Spring Cloud Zuul API服务网关之请求路由

    目录 一.Zuul 介绍 二.构建Spring Cloud Zuul网关 构建网关 请求路由 请求过滤 三.路由详解 一.Zuul 介绍 ​ 通过前几篇文章的介绍,我们了解了Spring Cloud ...

  8. PHP面向对象——构造函数、析构函数

    在PHP中构造函数和析构函数是固定的,如下: // 构造函数 function __construct([argument1,argument2,...,argumentN]){ /* Class i ...

  9. 小鬼PSer

    我是小鬼PSer,主要修图和做网站的,有需要可以call QQ:1805843351 微信:1805843351

  10. Jquery datepicker的使用

    1. 设定初始日期 $("#<%=txtStart.ClientID %>").datepicker("setDate", start); 2. 设 ...