一、算法核心思想
分步走策略:
-
找所有可能子串:从最长子串开始检查
-
查重复出现:对每个子串检查是否有其他相同子串
-
立即返回:找到第一个满足条件的最长子串
二、分步骤详解
步骤1:初始化
-
设定最长可能子串长度
l = 字符串长度-1
-
从长到短遍历所有可能长度
步骤2:遍历所有起始位置
-
对每个长度
l
,检查所有可能的起始位置i
(第一个子串的起点)
步骤3:查找匹配子串
-
对每个起始位置
i
,检查后续所有可能的起始位置j
(第二个子串的起点) -
必须满足
j > i
避免重复比较相同位置
步骤4:逐字符比较
-
比较从
i
和j
开始的l
个字符 -
发现完全匹配时立即记录结果并返回
三、时间复杂度分析
-
最坏情况:O(n⁴) (当完全没有重复子串时)
-
最优情况:O(n²) (当第一个最长子串出现在最前位置)
四、完整测试代码:
#include <cstring>
using namespace std;
const int MAX_LEN = 100; // 最大字符串长度
// 自定义字符串结构
struct MyString {
char data[MAX_LEN];
int length;
};
// 查找最长重复子串(使用引用传参)
void findLongestRepeatingSubstring(MyString &S, int &start, int &length) {
length = 0; // 最长重复子串长度
start = -1; // 起始位置
// 从最长可能长度开始检查
for (int l = S.length - 1; l > 0; l--) {
// 遍历所有起始位置i
for (int i = 0; i <= S.length - l; i++) {
// 检查后续起始位置j
for (int j = i + 1; j <= S.length - l; j++) {
bool match = true;
// 逐个字符比较
for (int k = 0; k < l; k++) {
if (S.data[i + k] != S.data[j + k]) {
match = false;
break;
}
}
// 找到重复子串
if (match) {
length = l;
start = i;
return; // 立即返回第一个找到的
}
}
}
}
}
int main() {
MyString S;
cout << "输入字符串(最大" << MAX_LEN-1 << "字符): ";
cin.getline(S.data, MAX_LEN);
S.length = strlen(S.data);
int start, length;
findLongestRepeatingSubstring(S, start, length);
if (length > 0) {
cout << "最长重复子串:";
for (int i = 0; i < length; i++) {
cout << S.data[start + i];
}
cout << endl;
cout << "起始位置:" << start << endl;
cout << "长度:" << length << endl;
} else {
cout << "没有重复子串" << endl;
}
return 0;
}
测试用例:
输入1:
ababcababc
输出1:
输入2:
hello!hello!
输出2:
输入3:
abcd
输出3:
该算法通过最直观的暴力搜索方式解决问题,虽不适用于超长字符串,但能够清晰展示问题解决的底层逻辑。