Find the shortest substring that contains all required characters and counts.
Start with the concrete trace below. It shows the state the algorithm must carry as it runs.
Problem trace
Minimum Window Substring: Maintain the exact deficit count while the right boundary gains characters and the left boundary removes only proven surplus.
Input and goalFind the shortest substring that contains all required characters and counts.
Initialize required countsFor text "ABAAC" and required "AAC", L = 0, the next R is 0, need has A:2 and C:1, and missing = 3.
LRA0B1A2A3C4
rangeempty before reading index 0requiredneed A:2, C:1missing3bestnone
saved stateA2C1
Expand through A at index 0need[A] was positive, so this A fills one requirement: missing becomes 2 and need[A] becomes 1.
LRA0B1A2A3C4
range[0..0] = "A"directionR reads index 0missing3 -> 2
saved stateA1C1
Expand through irrelevant Bneed[B] is 0, so B does not change missing; decrementing need[B] to -1 records one removable surplus.
LA0RB1A2A3C4
range[0..1] = "AB"directionR: 0 -> 1missing2
saved stateA1B-1C1
Expand through the second Aneed[A] was 1, so index 2 fills the second required A: missing becomes 1 and need[A] becomes 0.
Remove surplus A, then measure againIncrement need[A] from -1 to 0 and move L to 1. Missing stays 0, so the next while iteration measures "BAAC" and saves its length 4.
Remove surplus B, then measure againAfter measuring "BAAC", increment need[B] from -1 to 0 and move L to 2. The next while iteration measures "AAC" and saves its length 3.
Return the shortest saved windowThe scan is complete and the saved slice starts at 2 with length 3, so the result is "AAC".
A0B1best LA2A3best RC4
range[2..4] = "AAC"result"AAC"
saved statebest_start2best_length3
Recognize it
Use it when a contiguous result must cover a multiset of required values and validity can be updated by adding or removing one boundary value.
Keep true
need[x] is the remaining deficit for x (negative means surplus), missing is the total number of required copies absent from [L..R], and best is the shortest valid window seen before the current transition.
Reuse it
When validity is monotone under expansion, grow until feasible, then remove leftmost surplus while feasible; a deficit counter can collapse a full multiset comparison into constant-time boundary updates.
Read it this way: For text "ABAAC" and required "AAC", L = 0, the next R is 0, need has A:2 and C:1, and missing = 3. Step through the frames to watch the state change. The last frame shows the answer or the stopping condition.
Pattern: Grow, then shrink a sliding window.
Simple idea: Move the right side until every required character is present. Then move
the left side while the window remains valid. Save the shortest valid window.
from collections import Counterdef min_window(text: str, required: str) -> str: if not required: return "" need = Counter(required) missing = len(required) left = 0 best_start = 0 best_length = len(text) + 1 for right, char in enumerate(text): if need[char] > 0: missing -= 1 need[char] -= 1 while missing == 0: length = right - left + 1 if length < best_length: best_start, best_length = left, length left_char = text[left] need[left_char] += 1 if need[left_char] > 0: missing += 1 left += 1 if best_length > len(text): return "" return text[best_start : best_start + best_length]