用后缀数组求两个串的最长公共子串的长度
详见罗穗骞的论文
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
#define MAXN 1000005
using namespace std;
int r[MAXN];
int wa[MAXN], wb[MAXN], wv[MAXN], tmp[MAXN];
int sa[MAXN]; //index range 1~n value range 0~n-1
int cmp(int *r, int a, int b, int l)
{
return r[a] == r[b] && r[a + l] == r[b + l];
}
void da(int *r, int *sa, int n, int m)
{
int i, j, p, *x = wa, *y = wb, *ws = tmp;
for (i = 0; i < m; i++) ws[i] = 0;
for (i = 0; i < n; i++) ws[x[i] = r[i]]++;
for (i = 1; i < m; i++) ws[i] += ws[i - 1];
for (i = n - 1; i >= 0; i--) sa[--ws[x[i]]] = i;
for (j = 1, p = 1; p < n; j *= 2, m = p)
{
for (p = 0, i = n - j; i < n; i++) y[p++] = i;
for (i = 0; i < n; i++)
if (sa[i] >= j) y[p++] = sa[i] - j;
for (i = 0; i < n; i++) wv[i] = x[y[i]];
for (i = 0; i < m; i++) ws[i] = 0;
for (i = 0; i < n; i++) ws[wv[i]]++;
for (i = 1; i < m; i++) ws[i] += ws[i - 1];
for (i = n - 1; i >= 0; i--) sa[--ws[wv[i]]] = y[i];
for (swap(x, y), p = 1, x[sa[0]] = 0, i = 1; i < n; i++)
x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
}
}
int rank[MAXN]; //index range 0~n-1 value range 1~n
int height[MAXN]; //index from 1 (height[1] = 0)
void calheight(int *r, int *sa, int n)
{
int i, j, k = 0;
for (i = 1; i <= n; ++i) rank[sa[i]] = i;
for (i = 0; i < n; height[rank[i++]] = k)
for (k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; ++k);
return;
}
char s1[MAXN], s2[MAXN];
int main()
{
while(scanf("%s%s", s1, s2) != EOF)
{
int len = strlen(s1);
strcat(s1, "$");
strcat(s1, s2);
int n = strlen(s1), m = 0;
for(int i = 0; i < n; i++)
{
m = max(m, (int)s1[i]);
r[i] = s1[i];
}
r[n] = 0;
da(r, sa, n + 1, m + 1); //注意是n + 1 ,原因去看论文
calheight(r, sa, n);
int res = 0;
for(int i = 1; i < n; i++)
if((sa[i - 1] < len && sa[i] >= len) || (sa[i - 1] >= len && sa[i] < len)) res = max(res, height[i]);
printf("%d\n", res);
}
return 0;
}
分享到:
相关推荐
【POJ 2774】要求求出两个字符串的最长公共子串,这可以通过后缀数组和LCP(Longest Common Prefix,最长公共前后缀)数组直接计算得出。 【POJ 3693】的问题更复杂一些,需要找出字符串中重复次数最多的连续重复子...
在POJ 3261的解题过程中,我们可能需要用到后缀数组的特性,比如求解字符串的最长重复子串,或者查找某个子串出现的所有位置。这些问题都可以通过比较后缀数组中的相邻元素之间的关系来解决。 在给出的压缩文件`poj...
"C++ 数组扩充"提示我们问题可能与如何在C++编程语言中处理数组的增长有关,而"poj 26_poj 2682_poj26"似乎是重复提及问题编号,可能是用户在整理文件时的习惯。 描述中提到的“数链思想”可能是指一种处理数组元素...
【标题】"树状数组练习:POJ 3067" 树状数组,也称为线段树(Segment Tree),是一种高效的数据结构,用于处理区间查询和修改问题。在这个问题中,我们通过分析POJ 3067的题目来探讨如何应用树状数组解决实际问题。...
一维树状数组(也称作 Fenwick Tree)是基于前缀和的一颗二叉树,每个节点存储了其所有子孙节点对应的数组区间之和。对于二维树状数组,我们将其扩展到两个维度,每个节点存储了对应矩形区域的和。对于一个 m × n ...
http://poj.grids.cn/problem?id=2774 POJ 2774 木棒加工 木材厂有一些原木,现在想把这些木头切割成一些长度相同的小段木头,需要得到的小段的数目是给定了。当然,我们希望得到的小段越长越好,你的任务是计算能够...
基于这些信息,我们可以推测“POJ 1159”问题可能是一个需要动态规划求解的典型问题,例如斐波那契序列、背包问题或者最长公共子序列等。滚动数组在这里起到了关键作用,帮助减少额外的存储需求。博客文章可能详细...
【标题】"树状数组练习:POJ 2481(JAVA)" 是一篇关于使用树状数组(也称为线段树)解决编程竞赛问题的文章。这篇文章可能详细讲解了如何运用这种数据结构来解决特定的问题POJ 2481。POJ(Programming Online Judge)...
此外,后缀数组与LCP(Longest Common Prefix,最长公共前后缀数组)结合使用,可以解决更复杂的字符串问题。通过了解后缀数组,我们可以解决如poj3261这样的模板题。 对于后缀数组的入门,推荐阅读的两篇文章是: ...
二维树状数组(也称为部分和数据结构或区间更新数据结构)是一种在计算机科学中用于高效处理动态数组求和查询的数据结构。它扩展了一维树状数组(也称作线段树),能够处理二维或多维的数组更新和查询操作。在POJ ...
poj 2744子串 答案 所用的是最简单的C语言
标题中的“图的深搜+树状数组练习 POJ 3321(JAVA)”指的是一个编程题目,其中涉及到图的深度优先搜索(DFS, Depth First Search)算法和树状数组(也称为线段树,Segment Tree)的数据结构。这个题目来源于POJ...
后缀数组可以用来快速找到字符串的最长公共前后缀、最长重复子串等,对于文本搜索和模式匹配问题非常有用。"suffix_array.cpp"文件可能包含了后缀数组的实现代码。 3. **最大权闭合子图**:在图论中,最大权闭合...
### POJ 2352 Stars - 树状数组与线段树实现 #### 题目背景 POJ 2352 Stars 是一道经典的算法题目,它提供了使用树状数组或线段树来解决的可能性。这两种数据结构都是为了高效处理区间查询问题而设计的。在这篇...
在对齐问题中,可能需要找出两个字符串之间的最长公共子序列或最长公共子串,这是字符串处理中的经典问题。 4. **贪心算法**:另一种可能的解决方案是贪心策略,通过每次做出局部最优选择,期望得到全局最优解。...
- 字符串处理:如KMP算法和后缀数组,用于字符串搜索和模式匹配,如`poj1035, poj3080`。 - 排序算法:如快速排序和归并排序,用于对数据进行排序,如`poj2388, poj2299`。 - 并查集:用于处理集合的合并和查询...
### ACM新手刷题攻略之POJ 在ACM竞赛领域,特别是对于初学者而言,选择合适的平台进行训练至关重要。POJ(Peking University Online Judge)作为国内最早且最知名的在线评测系统之一,拥有丰富的题库资源,对于提高...
1. **高级数据结构**:如树状数组、线段树(poj2528, poj2828, poj2777, poj2886, poj2750)。 2. **平衡树**:如AVL树、红黑树等(poj2482, poj2352)。 3. **并查集**:用于处理不相交集合的问题(poj1195, poj...
【标题】"POJ.rar_poj java_poj1048" 涉及的知识点主要围绕编程竞赛中的“约瑟夫环”问题,这里是一个加强版,使用Java语言进行解决。 【描述】"POJ1048,加强版的约瑟夫问题 难度中等" 提示我们,这个问题是编程...
在程序设计语言中,可以利用堆栈的方法把中缀表达式转换成保值的后缀表达式(又称逆波兰表示法),并最终变为计算机可以直接执行的指令,得到表达式的值。 给定一个中缀表达式,编写程序,利用堆栈的方法,计算...