1. 2D Dynamic Programming (DP Table)
Intuition
Define dp[i][j] as the starting index in s1 (1-indexed) of the shortest substring ending at s1[i-1] that contains s2[0...j-1] as a subsequence. If s1[i-1] == s2[j-1], dp[i][j] = dp[i-1][j-1]. Else dp[i][j] = dp[i-1][j]. Find the minimum window length across all dp[i][T].
When to apply: Standard DP table formulation.
Algorithm
- Initialize
dp[S + 1][T + 1]with 0. - For
ifrom 1 toS:dp[i][0] = i. - For
ifrom 1 toS: - For
jfrom 1 toT: - If
s1[i-1] == s2[j-1]:dp[i][j] = dp[i-1][j-1]. - Else:
dp[i][j] = dp[i-1][j]. - Find minimum
i - dp[i][T] + 1among validdp[i][T] > 0. - Return minimum substring or empty string.
#include <iostream>#include <string>#include <vector> class Solution {public: std::string minWindow(std::string s1, std::string s2) { int m = s1.size(), n = s2.size(); std::vector<std::vector<int>> dp(m + 1, std::vector<int>(n + 1, 0)); for (int i = 0; i <= m; ++i) dp[i][0] = i + 1; for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (s1[i - 1] == s2[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = dp[i - 1][j]; } } } int start = 0, minLen = m + 1; for (int i = 1; i <= m; ++i) { if (dp[i][n] > 0) { int len = i - dp[i][n] + 1; if (len < minLen) { minLen = len; start = dp[i][n] - 1; } } } return minLen == m + 1 ? "" : s1.substr(start, minLen); }}; int main() { Solution sol; std::cout << sol.minWindow("abcdebdde", "bde") << std::endl; // bcde return 0;}Time & Space Complexity
- Time complexity:
O(S * T)— Fills an S x T dynamic programming table. - Space complexity:
O(S * T)
Why Brute Force Doesn't Scale:
Bidirectional two-pointer scanning achieves O(1) auxiliary memory.
Zero table allocations.