#include <stdio.h>
#include <string.h>
#define DEBUG
#ifdef DEBUG
#define debug(...) printf( __VA_ARGS__)
#else
#define debug(...)
#endif
#define maxn 200004
#define MIN(a, b) (a) < (b) ? (a) : (b)
int wx[maxn],wy[maxn],c[maxn], h[maxn];
int sa[maxn], *rank, height[maxn];
int cmp(int *r,int a,int b,int l)
{
return r[a] == r[b] && r[a+l] == r[b+l]; /* r[a] == r[b]就意味着a+l和b+l不会越界 */
}
/* 倍增法求后缀数组, 所有数组都从下标0开始 */
void da(char *r,int *sa,int n,int m)
{
int i,l,p,*x=wx,*y=wy,*t;
// 初始化x[i],同时根据源字符串r得到第一轮的SA
for(i = 0; i <= m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[i] = r[i]]++;
for(i = 1; i <= m; i++) c[i] += c[i-1];
for(i = n-1; i >= 0; i--) sa[--c[r[i]]] = i;
//继续迭代,根据x计算SA
for(l = 1,p = 1; p < n; l <<= 1, m = p) /* p表示不同字符串的个数, p = n说明排序结束 */
{
// 根据上一次求出的sa,对第二关键字排序,结果保存在y[i]中, y[i] = j表示第i名的后缀是suffix[j]
for(p = 0,i = n-l; i < n; i++) { /* 第二关键字超出范围的后缀排在最前面 */
y[p++] = i;
}
for(i = 0; i < n; i++) {
if(sa[i] >= l) {
y[p++] = sa[i]-l;
}
}
//对第一关键字使用计数排序, 生成SA
for(i = 0; i <= m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[y[i]]]++;
for(i = 1; i <= m; i++) c[i] += c[i-1];
for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
//根据SA生成rank,保存在数组x中,x[i] = j表示suffix[i]排在第j位, 相同的后缀名次相同,
//所以还要根据上次的x数组来判断两个后缀是否一样,优化点:
//交换x和y,这样y指向上次的x,原来y指向的空间用来存放新生成的rank
for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++) {
x[sa[i]] = cmp(y, sa[i-1], sa[i], l) ? p-1 : p++;
}
}
rank = x;
}
int main()
{
int i, s, t, n, n1, max_len;
char r[maxn], line[maxn];
gets(r);
n1 = strlen(r);
gets(line);
strcat(r, line);
n = strlen(r)+1; /* 一定要把末尾的\0也算进去 */
max_len = -1;
// 求后缀数组sa和排名数组wy
da(r, sa, n, 156);
// 求h[0]...h[n-1]
for (i = 0; i < n; i++) {
if (rank[i] == 1) h[i] = 0;
else if (i == 0 || h[i-1] <= 1) {
for (s = i, t = sa[rank[i]-1], h[i] = 0; r[s++] == r[t++]; h[i]++);
}
else {
h[i] = h[i-1]-1;
for (s = i+h[i], t = sa[rank[i]-1]+h[i]; r[s++] == r[t++]; h[i]++);
}
}
//求height[1]...height[n]
height[1] = 0;
for (i = 2; i <= n; i++) {
height[i] = h[sa[i]];
// 后缀的最长前缀肯定出现在两个排名相邻的后缀之间,即height[i]的最大值
// 而且两个后缀要属于不同的字符串
if (((sa[i] < n1 && sa[i-1] >= n1) || (sa[i-1] < n1 && sa[i] >= n1)) && height[i] > max_len) {
max_len = height[i];
}
}
printf("%d\n", max_len);
return 0;
}
相关推荐
http://poj.grids.cn/problem?id=2774 POJ 2774 木棒加工 木材厂有一些原木,现在想把这些木头切割成一些长度相同的小段木头,需要得到的小段的数目是给定了。当然,我们希望得到的小段越长越好,你的任务是计算能够...
在程序设计语言中,可以利用堆栈的方法把中缀表达式转换成保值的后缀表达式(又称逆波兰表示法),并最终变为计算机可以直接执行的指令,得到表达式的值。 给定一个中缀表达式,编写程序,利用堆栈的方法,计算...
只是poj上的一条题目,对于理解后缀数组很有帮助.poj3261
这是一道很不错的题目,即可以用线段树做也可以用树状数组,可谓经典。不过当然了线段树是比较难搞,而树状数组是极其简洁的,构造很简单,下面就分别来介绍一下两种方法...
poj上的题,音乐主题,首先需要对给定的数组差分,之后就是用后缀数组就行
NULL 博文链接:https://128kj.iteye.com/blog/1744222
POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类
原理为:以数链思想,移动数组中的内容 使数组在没有扩充情况下,达成移动的效果 当然,有更简单的,大牛不要笑哦
poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题...
NULL 博文链接:https://128kj.iteye.com/blog/1757060
NULL 博文链接:https://128kj.iteye.com/blog/1744555
NULL 博文链接:https://128kj.iteye.com/blog/1747400
POJ第1861题源码 POJ第1861题源码 POJ第1861题源码
NULL 博文链接:https://128kj.iteye.com/blog/1745671
北大POJ1159-Palindrome 解题报告+AC代码
C语言 poj npu 西工大 C语言Poj答案全完整打包,给有需要的朋友
poj 3414解题报告poj 3414解题报告poj 3414解题报告poj 3414解题报告
poj分类poj分类poj分类poj分类
本模板包括字典树,后缀数组,都是POJ上遇到的,然后编写成模板
北大POJ2002-Squares 解题报告+AC代码