求解一个字符串中出现的最长的重复的字符串,可以重叠
可以使用后缀数组的解法,先建立后缀数组,然后将数组排序,最后比较相邻的数组之间是否存在相同字符子串
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
vector<string> suffixtree(string s) {
vector<string> vs(s.length());//用vs来保存这些元素
for (int i = 0; i<s.length(); i++) {
//依次将后i个元素放入vs中
vs[i] = s.substr(s.length() - i - 1, i + 1);
}
//排序并返回
sort(vs.begin(), vs.end());
return vs;
}
string longcom(vector<string> vs) {
int maxLen = 0;
string ret;
for (int i = 0; i<vs.size() - 1; i++) {
string cur = vs[i];
string suf = vs[i + 1];
int tlen = 0;
//循环条件是尚未到达任意一个的末尾
for (int j = 0; j<min(cur.length(), suf.length()); j++) {
//如果发现有不匹配,立刻退出循环,
//如果是第一个元素就不匹配,那么没有必要匹配下去
//如果是后面的元素不匹配,那么在上一次循环中已经设置了maxLen
if (cur[j] != suf[j]) {
tlen = 0;
break;
}
else if (cur[j] == suf[j]) {
tlen++;
}
//更新maxLen
if (maxLen<tlen) {
maxLen = tlen;
ret = suf.substr(0, maxLen);
}
}
}
return ret;
}
int main()
{
vector<string> vec = suffixtree( "xasdasdvdvdvd" );
string str = longcom(vec);
cout << str;
}
解法二:KMP算法,注意此时的Next数组应该是没有经过优化的
#include<iostream>
using namespace std;
int getNext(char *str, int *next)
{
int len = strlen(str);
int j = 0;
int k = -1;
next[0] = k;
int max = 0;
//kmp算法求next值,取得最大的字串
while (j<len)
{
if (k == -1 || str[j] == str[k])
{
k++;
j++;
next[j] = k;
if (k>max)//求得其中重复最大的字串的个数,也就是与最前面串的重复数
{
max = k;
}
}
else
k = next[k];
}
return max;
}
int main()
{
char str[50];//输入字符串
cin >> str;
int max = 0;//最大的字串
int nextMax;//接受getNext函数中返回的最大值
int index;
int maxIndex;//保存最大的字串起始位置
int len = strlen(str);
//将一个字符串从开始一直减少到只剩一个字符,通过这个取得最小字串
for (index = 0; index<len - 1; index++)
{
int *next = new int[len - index];//取得next在这没用
nextMax = getNext(str + index, next);//每次从str+index开始
if (nextMax>max)
{
max = nextMax;
maxIndex = index;
}
}
//输出最长字串
cout << "最长字串: ";
for (index = 0; index<max; index++)
{
cout << str[index + maxIndex];
}
cout << endl;
return 0;
}