`
kenby
  • 浏览: 724599 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

poj 2774 后缀数组

 
阅读更多
#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;
}
 
分享到:
评论

相关推荐

    后缀数组相关题解1

    【POJ 2774】要求求出两个字符串的最长公共子串,这可以通过后缀数组和LCP(Longest Common Prefix,最长公共前后缀)数组直接计算得出。 【POJ 3693】的问题更复杂一些,需要找出字符串中重复次数最多的连续重复子...

    poj3261.zip_POJ 3261

    《POJ 3261:深入理解后缀数组及其应用》 在计算机科学与信息技术领域,算法设计和分析是核心部分,而字符串处理问题是其中不可或缺的议题。POJ 3261是一道经典的在线编程竞赛题目,它涉及到一个重要的数据结构——...

    字符串进阶前导知识1

    通过了解后缀数组,我们可以解决如poj3261这样的模板题。 对于后缀数组的入门,推荐阅读的两篇文章是: 1. https://www.cnblogs.com/nietzsche-oier/articles/6621881.html 2. ...

    music theme

    poj上的题,音乐主题,首先需要对给定的数组差分,之后就是用后缀数组就行

    经典 的POJ 分类

    - POJ 2031、POJ 1039:后缀数组的构建与应用。 #### 字典树 (Trie) - **题目示例**: - POJ 2513:Trie树的基本构造与查询。 ### 编程技巧 #### C++模板应用 - **题目示例**: - POJ 3096、POJ 3007:模板...

    poj训练计划.doc

    - 字符串处理:如KMP算法和后缀数组,用于字符串搜索和模式匹配,如`poj1035, poj3080`。 - 排序算法:如快速排序和归并排序,用于对数据进行排序,如`poj2388, poj2299`。 - 并查集:用于处理集合的合并和查询...

    algorithms-and-data-structures.rar_algorithms

    "algorithms-and-data-structures.rar_algorithms"这个压缩包文件聚焦于几个关键的算法和概念,包括线段树、后缀数组、最大权闭合子图、求逆元、斜率优化以及强连通分量。下面我们将详细探讨这些知识点。 1. **线段...

    acm新手刷题攻略之poj

    - 后缀数组可以高效地解决字符串相关问题。 4. **区间查询** - 推荐题目:[poj3264](https://vjudge.net/problem/POJ-3264)、[poj3368](https://vjudge.net/problem/POJ-3368) - 区间查询问题通常涉及线段树或...

    acm训练计划(poj的题)

    5. **后缀数组/后缀自动机**: - (poj1703, 2492):用于文本检索的强大工具。 6. **KMP算法**: - (poj1961, poj2406):高效的字符串匹配算法。 ### 十、进阶状态压缩 1. **状态压缩技巧**: - 如何高效地表示...

    字符串题目记录

    字符串题目记录是 ACM 题目中的一种常见类型,涉及到字符串处理、哈希、后缀数组、KMP 算法等多种知识点。下面是对标题、描述、标签和部分内容的详细解释和知识点总结。 标题:字符串题目记录 该标题表明了问题的...

    各种算法模板

    本资源“各种算法模板”聚焦于两种常见的数据结构和算法:字典树(Trie)和后缀数组(Suffix Array),这些都是在解决编程竞赛如POJ(Programming Online Judge)时经常遇到的工具。 **字典树**,又称为前缀树或...

    ACMer需要掌握的算法讲解 (2).docx

    ACM算法讲解 本文将对ACM主要算法进行讲解,涵盖了基本算法、图算法、数据结构、搜索、计算几何学、动态规划和综合题等多方面的知识点。 一、基本算法 ... + 后缀数组、后缀树 + 块状链表 + 哈夫曼树

    本人整理的POJ解题报告大全

    8. **字符串处理**:涉及到模式匹配、KMP算法、后缀数组等,对于文本处理和信息检索至关重要。 9. **数学问题**:如数论、组合数学、线性代数等,它们在解决特定类型的算法问题时不可或缺。 10. **递归与分治**:...

    poj(百练)题目分类

    - 特殊的数据结构:后缀数组、LCP数组等用于文本处理的高效结构。 #### 6. 几何题 几何题通常涉及到几何图形的性质、计算等。 - **知识点**: - 几何对象的表示方法:点、线、面等。 - 几何计算的基础公式,如...

    我的Poj里的一些AC代码

    7. **字符串处理**:涉及到模式匹配、KMP算法、后缀数组或AC自动机等字符串相关的算法。 8. **数学技巧**:可能涉及数论、组合数学、模运算、矩阵快速幂等数学知识。 9. **编码技巧**:在ACM竞赛中,代码效率至关...

    POJ题目分类

    - **内容**: 后缀数组是字符串的所有后缀按字典序排序后的数组。 - **示例题目**: poj3278, poj1426, poj3126, poj3087, poj3414 #### 4. 字符串搜索 - **内容**: 包括后缀树、AC自动机等字符串搜索算法。 - **...

    ACMer需要掌握的算法讲解.docx

    ACMer 需要掌握的算法讲解 本资源摘要信息涵盖了 ACM 主要算法的介绍,包括基本算法、图算法、数据结构、搜索、计算几何学、动态规划、综合题等方面的知识点。...13. 后缀数组、后缀树 14. 块状链表 15. 哈夫曼树

    ACM 题型

    2. **后缀数组** - 示例题目:poj2031, poj1039 3. **后缀自动机** - 示例题目:poj1408, poj1584 4. **后缀树** - 示例题目:poj2187, poj1113 #### 高级算法 1. **高级搜索** - 示例题目:poj3096, poj...

    POJ经典268题的源码,ACMer必备

    4. **字符串处理**:KMP算法、后缀数组、Manacher算法等。 5. **数学应用**:组合数学、数论、模运算、矩阵快速幂等。 6. **计算几何**:点线段查询、最短路径、旋转卡壳等。 7. **模拟与建模**:根据题目需求进行的...

Global site tag (gtag.js) - Google Analytics