最长重复子串(转)

预备知识:
1. sort 使用时得注明:using namespace std; 或直接打 std::sort() 还得加上 #include <algorithm>
2. qort是qsort的升级版,如果能用sort尽量用sort,使用也比较简单,不像qsort还得自己去写 cmp 函数,
只要注明 使用的库函数就可以使用,参数只有两个(如果是普通用法)头指针和尾指针;

3. 默认sort排序后是升序,如果想让他降序排列,可以使用自己编的cmp函数

bool compare(int a,int b){
return a>b; //降序排列,如果改为return a<b,则为升序
}
sort(*a,*b,cmp);

4. compare 函数中对于double需要特别注意返回值的问题,
显然cmp返回的是一个整型,所以避免double返回小数而被丢失。

int cmp( const void *a , const void *b ){
return *(double *)a > *(double *)b ? 1 : -1;
}

分析:要求输出它及其首字符的位置。 例如字符串yyabcdabjcabceg,输出结果应该是abc和3。

1.可以将上面字符串分解为,后缀数组形式。
substrs[0] =yyabcdabjcabceg;
substrs[1] =yabcdabjcabceg;
substrs[2] =abcdabjcabceg;
substrs[3] =bcdabjcabceg;
substrs[4] =cdabjcabceg;
substrs[5] =dabjcabceg;
substrs[6] =abjcabceg;
substrs[7] =bjcabceg;
substrs[8] =jcabceg;
substrs[9] =cabceg;
substrs[10]=abceg;
substrs[11]=bceg;
substrs[12]=ceg;
substrs[13]=eg;
substrs[14]=g;

2.对这些字符串按照字典顺序排序,

3.然后比较相邻字符串的前驱,找到最长的匹配项。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

pair<int, string> fun(const string &str)
{
	vector<string> substrs;
	int maxcount = 1;
	unsigned int count = 0;
	string substr;
	int i, len = str.length();

	for (i = 0; i < len; i++)   // 得到所有的后缀子串
	{
		// basic_string substr(size_type pos = 0,size_type n = npos) const;
		// 从pos开始,截取n个字符组成的字符串。
		substrs.push_back(str.substr(i, len-i));
	}

	// 后缀树排序
	sort(substrs.begin(), substrs.end());

	// 比较相邻两个字符串公共序列
	string str1;
	string str2;
	vector<string>::iterator iter;
	for(iter = substrs.begin(); iter != substrs.end()-1; ){
		count = 0;
		str1 = *iter++;
		str2 = *iter;

		while(	count < str1.length() &&  count < str2.length()  &&  (str1.at(count) == str2.at(count))	)
			count++;

		if(count > maxcount){
			maxcount = count;
			substr = str1.substr(0, maxcount);
		}

	}

	substrs.clear();
	return make_pair(maxcount,substr);
}

int main()
{
	string str;
	pair<int, string> rs;
	while (cin >> str)
	{
		rs = fun(str);
		cout << rs.second << ‘:‘ << rs.first << endl;
	}
	return 0;
}

  

下面是另一种解题思路:
时间复杂度比上面介绍的要高,但是空间复杂度为O(1).时间换空间。
思路:对源字符串所有后缀的所有子串,从每一个后缀的最长子串开始,
分别从前向和后向开始在源字符串中查找匹配的子串,
若两次查找位置不一致则说明存在重复的长度最长的字串,并返回前向查找时的位置。
e.g. string = “abcedfghiabckl‘,当使用子串”abc“在源字符串中分别前向和后向匹配时,
找到的位置分别为pos1=0, pos2 = 9.

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string str,tep;
	cin>>str;
	cout<<"length=="<<str.length()<<endl;
	for (int i = str.length()-1; i>=1; i--)
	{
		for (int j = 0; j < str.length(); j++)
		{
			// 如果没有这句的约束,那么结果错误。
			// 这句话使得每次得到的tep的长度是i,即满足从大到小取字符串。
			if (j + i <= str.length())
			{
				size_t t = 0;
				size_t num = 0;
				tep = str.substr(j, i); // 从大到小取字串。i是截取的字符串的长度,先截取最长的,再截取次长的
				t = str.find(tep);		// 正序查找
				num = str.rfind(tep);	// 逆序查找
				// 如果两次查找的位置不一样,说明存在重复字串。
				if (t != num)			// 满足条件就输出,因为是从最长的字符串开始截取。
				{
					cout<<tep<<" "<<t<<endl;
					return 0;
				}
			}
		}
	}
	return 0;
}

  

最长重复子串(转)

时间: 2024-10-13 05:05:45

最长重复子串(转)的相关文章

字符串中连续出现最多的子串 &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 ......

自己写的一个后缀树算法查找一个字符串的最长重复子串

在上个星期面试一家公司的笔试题上面的最后一道题就是写程序查找一个字符串的最长重复子串.当时想了很长时间没想出什么好方法,就把一个算法复杂度比较高的算法写上去了.回来上机把那个算法写了一遍测试没问题,然后自己又到网上面查查还有什么方法,然后发现好像有种叫做后缀树的方法,然后看那个方法,当时没给出代码,看图看了老半天加之自己想了好几个小时终于知道后缀树是个什么东西.然后自己萌生了一个自己写一个后缀树算法解决那个重复子串的问题.然后写了一天终于写出来了.后续有做了一些测试,发现自己写的一个只有几十个字

面试题[后缀数组]: 最长重复子串

题目:给定一个字符串,求出最长重复子串. 这个题目可以用后缀数组来解:对后缀数组排好序,这样重复的子串就在相邻的后缀中找就可以了.我的C++代码实现如下: class Solution { public: string LongestRepeatingSubstring(string str) { size_t len = str.size(); vector<string> SuffixArray(len); for (size_t i = 0; i < len; ++i) Suffi

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

参考: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=

POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)

Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 14094   Accepted: 6244 Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation,

【POJ1743】不可重叠最长重复子串

题意:求一个字符串里两个不重叠的最长重复子串 代码如下: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 int sa[20010],rank[20010],y[20010],Rsort[20010]; 8 int wr[20010],a[20010],height[20010],n; 9 10

POJ 3261 可重叠的 k 次最长重复子串【后缀数组】

这也是一道例题 给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠.算法分析:这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组.不同的是,这里要判断的是有没有一个组的后缀个数不小于 k.如果有,那么存在k 个相同的子串满足条件,否则不存在.这个做法的时间复杂度为 O(nlogn). Source Code: //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include

POJ - 3261 Milk Patterns (后缀数组求可重叠的 k 次最长重复子串)

Description Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular pattern

KMP(最长重复子串 &amp; 最小覆盖)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 如果一个长度 L 字符串是由 n 个长度 L / n 子串构成的.那么最后一个字符的next值是L-L/n吧: 例如: 一个字符串:abbabbabbabbabb(一共15个字符) next[15]=12吧! 我们拿:15 - 12 = 3 就是最长重复子串的长度 现在说一般情况: 假设 next[length] = k 如果 k % length == 0 那 length /

poj 3261 求可重叠的k次最长重复子串

题意:求可重叠的k次最长重复子串的长度 链接:点我 和poj1743差不多 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000