字符串中连续出现最多的子串 & 字符串中最长反复子串

字符串中连续出现最多的子串 & 字符串中最长反复子串

字符串中连续出现最多的子串 & 字符串中最长反复子串,这两个问题都能够用后缀数组来表示,至于后缀数组能够參考编程珠玑P156;后缀数组就是定义一个数组指针,分别指向字符串中的相应位置,例如以下:

a b c a b c a b c d e .substr[0]

b c a b c a b c d e ....substr[1]

c a b c a b c d e .......substr[2]

a b c a b c d e ..........substr[3]

b c a b c d e .............substr[4]

c a b c d e ...............substr[5]

a b c d e .................substr[6]

b c d e ...................substr[7]

c d e .....................substr[8]

d e ........................substr[9]

e ..........................substr[10]

上面的 substr 就是abcabcabcde的后缀数组;

一、字符串中连续出现最多的子串

针对这个问题能够使用后缀数组的思想,能够看到,子串连续出现,则满足 substr[0].substr(i, j - i) = substr[j].substr(0, j - i)。知道了这一点程序就好编写了,下面是C++代码:

<span style="font-size:18px;">string MaxTimesOfContinue(string str)
{
	int len = str.length();
	int maxCount = 0;
	string longest = "";
	for (int i = 0; i < len; ++i)
	{
		for (int j = i + 1; j < len; ++j)
		{
			if (str.substr(i, j - i) == str.substr(j, j - i))
			{
				int offset = j - i;
				int count = 2;
				for (int k = j + offset; j <= len; k += offset)
				{
					if (str.substr(i, offset) == str.substr(k, offset))
						++count;
					else
						break;
				}
				if (count > maxCount)
				{
					maxCount = count;
					longest = str.substr(i, offset);
				}
			}
		}
	}
	return longest;
}</span>

二、字符串中最长反复子串

这个问题相同能够用后缀数组的思想来做,当然開始肯定想到的是暴力法,即求全部反复子串的长度,之后选择一个最长的就可以。

int Comlen(char *str1, char *str2)
{
	int i = 0;
	while(*str2 && (*str1++ == *str2++))
		++i;
	return i;
}

int MaxLength(char *str)
{
	if(str == NULL)
		return 0;
	int maxLen = 0;
	int n = strlen(str);
	int maxi, maxj;
	for (int i = 0; i < n; ++i)
	{
		for(int j = i + 1; j < n; ++j)
		{
			int thisLen = 0;
			if ((thisLen = Comlen(&str[i], &str[j])) > maxLen)
			{
				maxLen = thisLen;
				maxi = i;
				maxj = j;
			}
		}
	}
	return maxLen;
}

若是使用后缀数组的方法能够:

对于字符串 banana,其后缀数组为

a[0]:banana

a[1]:anana

a[2]:nana

a[3]:ana

a[4]:na

a[5]:a

将后缀数组按字典排序

a[0]:a

a[1]:ana

a[2]:anana

a[3]:banana

a[4]:na

a[5]:nana

之后比較相邻两个子串就可以:

int Comlen(char *str1, char *str2)
{
	int i = 0;
	while(*str2 && (*str1++ == *str2++))
		++i;
	return i;
}
int	Pstrcmp(const void *a, const void *b)
{
	return  strcmp(*(char**)a, *(char**)b);
}
//char *a[11];
int MaxLength(char *str)
{
	if(str == NULL)
		return 0;
	int maxLen = 0;
	int len = strlen(str);
	char **a = new char *[len + 1];
	for (int i = 0; i < len ; ++i)
		a[i] = &str[i];
	qsort(a, len , sizeof(char *), Pstrcmp);
	for (int i = 0; i < len - 1; ++i)
		if(Comlen(a[i], a[i+1]) > maxLen)
			maxLen = Comlen(a[i], a[i+1]);
	return maxLen;
}
时间: 2024-08-06 07:50:44

字符串中连续出现最多的子串 &amp; 字符串中最长反复子串的相关文章

字符串中连续出现最多的子串 &amp; 字符串中最长重复子串

字符串中连续出现最多的子串 & 字符串中最长重复子串 字符串中连续出现最多的子串 & 字符串中最长重复子串,这两个问题都可以用后缀数组来表示,至于后缀数组可以参考编程珠玑P156:后缀数组就是定义一个数组指针,分别指向字符串中的对应位置,如下: a b c a b c a b c d e .substr[0] b c a b c a b c d e ....substr[1] c a b c a b c d e .......substr[2] a b c a b c d e ......

求一个字符串中连续出现最多的子串次数

时间:2014.09.12 地点:基地 心情:明天就要和欧阳去武汉面试阿里了,整理一下同学求助的一道题,写下这一篇,愿一切顺利. 一.题目: 求一个字符串中连续出现最多的子串次数:例如字符串abcbcbcabc,连续出现次数最多的子串是bc,出现次数为3. 二.分析 方法:后缀思路 比如题目中举例中的字符串,它的后缀有: abcbcbcabc  0 bcbcbcabc  1 cbcbcabc  2 bcbcabc  3 cbcabc  4 bcabc  5 cabc  6 abc  7 bc  

程序员面试题目总结--数组(三)【旋转数组的最小数字、旋转数组中查找指定数、两个排序数组所有元素中间值、数组中重复次数最多的数、数组中出现次数超过一半的数】

转!http://blog.csdn.net/dabusideqiang/article/details/38271661 11.求旋转数组的最小数字 题目:输入一个排好序的数组的一个旋转,输出旋转数组的最小元素. 分析:数组的旋转:把一个数组最开始的若干个元素搬到数组的末尾.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1.这道题最直观的解法并不难.从头到尾遍历数组一次,就能找出最小的元素,时间复杂度显然是O(N).但这个思路没有利用输入数组

jq中连续删除的操作;以及js中连续删除的操作;jq方法中如何写循环。

jq中连续删除的操作 采用的是用父节点的来进行删除,不能直接利用$(XXX)来回去父节点来进行删除.存在逻辑上的错误. js中的连续删除 和jq中删除是一个道理,同样实在利用父节点去删除子节点.获取当前单击元素的父节点.利用来删除子节点. 至于寻找祖先中的哪一个,就要看,要删除的什么内容了. jq方法中如何写循环. jq中写循环,一般应该用each进行循环.但是利用for循环也是可以.但是有一个需要注意的地方.for循环不能在jq中的方法中出现,不会执行.也就是说,在jq中需要去写一个新的方法,

hihoCoder - 1032 - 最长回文子串 (字符串~)

#1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:"小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?" 小Ho奇怪的问道:"什么叫做最长回文子串呢?" 小Hi回答道:"一个字符串中连续的一

一天一道算法题(5)---最长公共子串

题目 给定两个字符串str1和str2,返回两个字符串的最长公共子串.例如:str1="1AB2345CD",str2="12345EF",公共子串是"2345" 解析 最长公共子串和最长公共子序列的区别是,子串是连续的,子序列是不连续的. 首先还是要生成动态规划表.生成大小为M*N的矩阵dp.dp[i][j]的含义是,在必须把str1[i]和str2[j]当作公共子串最后一个字符的情况下,公共子串最长能有多长.比如,str1="A12

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和

参考:http://www.ahathinking.com/archives/124.html 最长公共子序列 1.动态规划解决过程 1)描述一个最长公共子序列 如果序列比较短,可以采用蛮力法枚举出X的所有子序列,然后检查是否是Y的子序列,并记录所发现的最长子序列.如果序列比较长,这种方法需要指数级时间,不切实际. LCS的最优子结构定理:设X={x1,x2,……,xm}和Y={y1,y2,……,yn}为两个序列,并设Z={z1.z2.……,zk}为X和Y的任意一个LCS,则: (1)如果xm=

动态规划 &amp; 最长公共子串算法(LCS)

求最长公共子串可以先求最长公共子串的长度,并且记录那些公共子串字符的长度以及字符,然后通过回溯可以找到所有的公共子串. 下面是求最长公共子串长度的动态规划方法. 1:决策,我们在最后一步需要做的决策是,是否要将A[n],B[m]加入公共子串序列中. 2:由 1 可知,若以DP[i][j]表示A[1..i] 与 B[1..j]的最长公共子串的长度,那么可以得到 (1) 若A[i] == B[j]  (即作出决策,将A[i],B[i]都加入公共子串) DP[i][j] = DP[i - 1][j -

利用后缀数组(suffix array)求最长公共子串(longest common substring)

摘要:本文讨论了最长公共子串的的相关算法的时间复杂度,然后在后缀数组的基础上提出了一个时间复杂度为o(n^2*logn),空间复杂度为o(n)的算法.该算法虽然不及动态规划和后缀树算法的复杂度低,但其重要的优势在于可以编码简单,代码易于理解,适合快速实现. 首先,来说明一下,LCS通常指的是公共最长子序列(Longest Common Subsequence,名称来源参见<算法导论>原书第3版p223),而不是公共最长子串(也称为最长公共子串). 最长公共子串问题是在文本串.模式串中寻找共有的