Minimum Window Subsequence

Smallest substring of S containing T as a subsequence (not contiguously) — two-pointer back-and-forth scan.

Hard
Time O(n * m) Space O(1)
LeetCode
5 min read
sliding-window string two-pointers

Problem#

Given strings s and t, find the smallest substring W of s such that t is a subsequence of W. If multiple, return the leftmost.

Examples#

  • s = "abcdebdde", t = "bde""bcde"
  • s = "jmeqksfrsdcmsiwvaovztaqenprpvnbstl", t = "u"""

Constraints#

  • 1 <= s.length <= 2 * 10^4, 1 <= t.length <= 100.

Hints#

Hint 1
Greedy forward match to locate a window end; then greedy backward match from that end to tighten the start.

Approach#

Two-pass per anchor: forward to find the earliest match-end r containing t as a subsequence starting at some l; then backward from r to find the latest match-start l' still consuming all of t. That gives the tightest window ending at r; advance to look for shorter windows.

Solution#

Minimum Window Subsequence
class Solution {
public:
string minWindow(string s, string t) {
const int n = s.size(), m = t.size();
int bestL = -1, bestLen = INT_MAX;
int i = 0;
while (i < n) {
int j = 0;
while (i < n && j < m) {
if (s[i] == t[j]) ++j;
++i;
}
if (j < m) break;
// Backward tighten from i-1.
int r = i - 1, k = m - 1;
while (k >= 0) {
if (s[r] == t[k]) --k;
--r;
}
int l = r + 1;
if (i - l < bestLen) {
bestLen = i - l;
bestL = l;
}
i = l + 1;
}
return bestL < 0 ? "" : s.substr(bestL, bestLen);
}
};

Editorial#

Sliding-window over multisets doesn’t apply here — subsequence matching is order-sensitive. The forward/backward two-pass gives the canonical greedy: find any window ending at r (forward), then move the start as far right as possible while preserving the match (backward). Restarting the search at l + 1 rather than l is what avoids quadratic re-scan for many inputs in practice.

Complexity#

  • Time: O(n × m) worst case.
  • Space: O(1).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.