区间动态规划例题:最小窗口子序列问题(字符串匹配最小窗口)
字数 1228 2025-11-08 10:02:38
区间动态规划例题:最小窗口子序列问题(字符串匹配最小窗口)
题目描述
给定一个字符串 S 和一个目标字符串 T,找出 S 中最短的连续子串(窗口),使得 T 是该子串的子序列。如果不存在这样的窗口,返回空字符串。
例如:
- 输入:
S = "abcdebdde",T = "bde" - 输出:
"bcde"(最短窗口为"bcde",其中T是子序列)
解题思路
-
问题分析:
- 需要找到
S中一个子串,使得T是其子序列(不必连续,但顺序一致)。 - 窗口应尽可能短,且包含
T的所有字符。
- 需要找到
-
关键观察:
- 若固定窗口的起始位置
i,可贪心匹配T:从i开始遍历S,按顺序匹配T的字符,匹配完时记录窗口长度。 - 但直接枚举所有起点效率低(O(n²))。需用动态规划优化匹配过程。
- 若固定窗口的起始位置
-
动态规划定义:
- 设
dp[i][j]表示在S的前i个字符中,匹配到T的第j个字符时,窗口的起始位置。 - 状态转移:
- 若
S[i-1] == T[j-1]:当前字符匹配,窗口起始点与dp[i-1][j-1]相同(即从匹配T的前一字符的起点开始)。 - 若
S[i-1] != T[j-1]:当前字符不匹配,窗口起始点与dp[i-1][j]相同(继承之前的起点)。
- 若
- 初始化:
dp[0][0] = 0,表示空匹配的起点为0;其他位置初始化为-1(未匹配)。
- 设
-
窗口计算:
- 当
j = len(T)时,说明T已匹配完成,此时窗口长度为i - dp[i][j]。 - 遍历所有
i,记录最小窗口的起始点和长度。
- 当
-
复杂度优化:
- 使用滚动数组将空间复杂度优化至 O(m)(m 为
T的长度)。
- 使用滚动数组将空间复杂度优化至 O(m)(m 为
详细步骤
- 初始化
dp数组,长度为m+1(m 为T的长度),dp[0] = 0,其余为-1。 - 遍历
S的每个字符S[i](i 从1开始):- 从后往前遍历
T的字符(避免覆盖状态):- 若
S[i-1] == T[j-1],则dp[j] = dp[j-1](匹配成功,起点继承上一状态)。 - 若
j=1且字符匹配,则dp[1] = i(匹配T的第一个字符时,起点为当前位置)。
- 若
- 从后往前遍历
- 当
j = m且dp[m] ≠ -1时,计算窗口长度i - dp[m] + 1,更新最小窗口。 - 返回最小窗口对应的子串。
举例说明
以 S = "abcdebdde", T = "bde" 为例:
- 匹配到
T的最后一个字符e时,窗口起点为dp[3](即匹配b时的位置),窗口长度为当前位置减起点。 - 最终找到最短窗口
"bcde"(起点为2,终点为5)。
通过此方法,时间复杂度为 O(n×m),空间复杂度为 O(m)。