php找最长重复子串的核心是找出至少出现两次且长度最大的子串;暴力法适合短字符串,优化方案用哈希表+降序长度扫描,时间复杂度o(n³)可改善,需注意重叠允许、边界处理及与其它子串问题的区别。

PHP 中找字符串的最长重复子串,核心是找出在原串中至少出现两次(允许重叠)且长度最大的那个子串。暴力法最易理解,适合短字符串;对长文本,建议用哈希 + 二分或后缀数组等优化方案,但 PHP 原生实现中暴力法已够日常使用。
暴力法:清晰直接,适合调试和小数据
枚举所有子串,对每个子串用 find 从后续位置查找是否再次出现。关键点有三个:
- 子串切片用 s[i:j] 形式(PHP 中为 substr($s, $i, $j - $i))
- 查找时起始位置设为 $i + 1,避免匹配自身位置
- 只更新更长的子串,不覆盖等长结果(保证“最长”而非“最先最长”)
优化思路:用哈希表提速重复判断
暴力法时间复杂度 O(n³),瓶颈在反复调用查找。可改用哈希表记录每个子串首次出现位置,第二次遇到即确认重复:
- 外层按长度从长到短遍历(如先试 len = n-1,再 len = n-2…),找到第一个有重复的长度就返回,不必穷举全部
- 内层遍历该长度下所有子串,substr 后存入关联数组:$seen[$sub] = $start_index
- 若键已存在,说明重复,立即返回该子串
注意边界与常见误区
“重复”不要求非重叠——例如 "aaaa" 的最长重复子串是 "aaa"(出现在 [0,2] 和 [1,3]),不是 "aa";
立即学习“PHP免费学习笔记(深入)”;
- 空字符串或单字符串返回空串
- 全不同字符(如 "abcde")应返回空串,而非任意单字符
- 区分“重复子串”和“最长公共子串”“最长回文子串”,目标不同,算法不能混用
一个简洁可用的 PHP 函数
以下函数采用优化后的哈希+降序长度扫描,兼顾可读性与效率:
function longest_repeating_substring($s) {$n = strlen($s);
if ($n // 从最长可能长度开始尝试(最多 n-1)
for ($len = $n - 1; $len >= 1; $len--) {
$seen = [];
for ($i = 0; $i $sub = substr($s, $i, $len);
if (isset($seen[$sub])) return $sub;
$seen[$sub] = $i;
}
}
return '';
}











