存档

文章标签 ‘后缀数组’

最长回文子串

2012年7月3日 12 条评论

---

题:给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度。回文就是正反读都是一样的字符串,如aba, abba等。

例如:aaaa与abab:最长的回文串长度分别为4、3。

解法一:(该解法有误,见勘误)

最先考虑到,这又是一个后缀数组的应用,一个字符串X如果含有回文子串,那么在其后面“连接”一个逆序X’, 类似最长公共子串的解决方法,通过后缀数组寻找,这个最长回文子串必然会出现两次,类似的,我们将串X变为X#X’,其中X’是X的逆序序列。之后的实现跟最长公共子串就基本一样了,代码如下:

阅读全文...

最长公共子串(Longest-Common-Substring,LCS)

2012年6月25日 7 条评论

---

这个LCS跟前面说的最长公共子序列的LCS不一样,不过也算是LCS的一个变体,在LCS中,子序列是不必要求连续的,而子串则是“连续”的。即:

题:给定两个字符串X,Y,求二者最长的公共子串,例如X=[aaaba],Y=[abaa]。二者的最长公共子串为[aba],长度为3。

本节给出三种不同的实现方式,并对比分析每种方法的复杂度,内容如下:

==基本算法==

==DP方案==

==后缀数组==

==各方法复杂度分析==

==================================

基本算法

其实对于最长公共子串,还是比较简单易想的,因为子串是连续的,这就方便了很多。最直接的方法就是用X每个子串与Y的每个子串做对比,求出最长的公共子串。代码如下:

阅读全文...

最长重复子串

2012年6月25日 5 条评论

---

首先这是一个单字符串问题。子字符串R 在字符串L 中至少出现两次,则称R 是L 的重复子串。重复子串又分为可重叠重复子串和不可重叠重复子串,这里只是简单讨论最长可重叠的重复子串,给出基本算法和基于后缀数组的算法;关于后缀数组,这里也只是用最简单的形式实现,对于后缀数组的倍增算法和DC3算法的实现以及不可重叠重复子串的问题可参见算法合集之《后缀数组——处理字符串的有力工具》,以后再整理这几个问题。

最直接的方法就是子串和子串间相互比较,这样查看所有的子串对,时间复杂度为O(n^2),代码如下:

/* 最长重复子串 Longest Repeat Substring */

int maxlen;    /* 记录最长重复子串长度 */
int maxindex;  /* 记录最长重复子串的起始位置 */
void outputLRS(char * arr);  /* 输出LRS */

/* 最长重复子串 基本算法 */
int comlen(char * p, char * q)
{
	int len = 0;
	while(*p && *q && *p++ == *q++)
	{
		++len;
	}
	return len;
}

void LRS_base(char * arr, int size)
{
	for(int i = 0; i < size; ++i)
	{
		for(int j = i+1; j < size; ++j)
		{
			int len = comlen(&arr[i],&arr[j]);
			if(len > maxlen)
			{
				maxlen = len;
				maxindex = i;
			}
		}
	}
	outputLRS(arr);
}

阅读全文...