最小覆盖子串需用滑动窗口算法实现:通过双指针维护窗口,统计目标串字符频次,动态扩展右指针、收缩左指针,实时更新满足条件的最短子串;若不存在则返回空字符串。

在 PHP 中实现“最小覆盖子串”(Minimum Window Substring)问题,核心是用滑动窗口(Sliding Window)算法在线性时间内找出包含目标字符串所有字符的最短连续子串。这不是 PHP 内置函数能直接解决的问题,需手动实现逻辑。
理解问题关键点
给定两个字符串 s(源串)和 t(目标串),要求找到 s 中最短的子串,使其包含 t 中每个字符(含重复)至少一次。例如:
- s = "ADOBECODEBANC", t = "ABC" → 结果为 "BANC"
- 注意:大小写敏感;t 中重复字符(如 "AAB")必须被覆盖对应次数
- 若不存在,返回空字符串
滑动窗口双指针实现思路
维护左右指针 left 和 right 构成窗口,用哈希数组统计字符频次:
- 先统计 t 中各字符出现次数(need 数组)
- 扩展 right,每遇到一个 t 中的字符,更新窗口内计数(window),并检查是否满足该字符所需数量
- 当窗口已覆盖全部字符(valid == need 的不同字符数),尝试收缩 left 缩小窗口
- 每次满足条件时,记录当前最小长度及起始位置
PHP 实现示例(无第三方依赖)
以下代码兼容 PHP 7.4+,使用关联数组模拟哈希表:
立即学习“PHP免费学习笔记(深入)”;
function minWindow($s, $t) {
if (strlen($s) $need = [];
$window = [];
for ($i = 0; $i < strlen($t); $i++) {
$c = $t[$i];
$need[$c] = ($need[$c] ?? 0) + 1;
}
$required = count($need); // 需要满足的不同字符数
$formed = 0; // 当前已满足的字符种类数
$left = $right = 0;
$ans = [-1, 0, 0]; // [len, left, right]
while ($right < strlen($s)) {
$c = $s[$right];
$window[$c] = ($window[$c] ?? 0) + 1;
if (isset($need[$c]) && $window[$c] === $need[$c]) {
$formed++;
}
while ($left <= $right && $formed === $required) {
$c2 = $s[$left];
if ($ans[0] === -1 || $right - $left + 1 < $ans[0]) {
$ans = [$right - $left + 1, $left, $right];
}
$window[$c2]--;
if (isset($need[$c2]) && $window[$c2] < $need[$c2]) {
$formed--;
}
$left++;
}
$right++;
}
return $ans[0] === -1 ? '' : substr($s, $ans[1], $ans[0]);}
调用:echo minWindow("ADOBECODEBANC", "ABC"); // 输出 "BANC"
注意事项与优化提示
- PHP 字符串支持下标访问(
$s[0]),无需str_split转数组,更高效 - 避免使用
array_key_exists频繁判断,用isset()更快 - 若 t 含 Unicode 多字节字符(如中文),需改用
mb_substr和mb_strlen,并逐码点处理 - 时间复杂度 O(|s|),空间复杂度 O(|t|),适合长文本场景











