区间动态规划例题:字符串交织问题(进阶版)
字数 1579 2025-11-04 20:47:20
区间动态规划例题:字符串交织问题(进阶版)
题目描述
给定三个字符串 s1、s2 和 s3,判断 s3 是否能由 s1 和 s2 的字符交错形成。交错形成是指:保持 s1 和 s2 的字符相对顺序不变,将它们穿插合并成 s3。
例如:
- 输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
- 输出:true
- 解释:s3 可由 s1 和 s2 交替取字符构成(如:s1取"aa"、s2取"dbbc"、s1取"bc"、s2取"a"、s1取"c")。
约束条件
- 0 ≤ |s1|, |s2|, |s3| ≤ 200
- 字符串仅包含小写字母
- 需保证 |s1| + |s2| = |s3|,否则直接返回 false
解题思路
-
问题分析
- 若直接尝试所有交错方式会是指数级复杂度,需用动态规划优化。
- 关键观察:
s3的前i+j个字符是否由s1的前i个字符和s2的前j个字符交织而成,取决于两个子问题的结果。
-
状态定义
- 定义
dp[i][j]表示s1的前i个字符和s2的前j个字符能否交织成s3的前i+j个字符。 - 注意:
i和j分别表示已使用的字符数(从0开始)。
- 定义
-
状态转移方程
- 初始状态:
dp[0][0] = true(空字符串可以交织成空字符串)。 - 对于
dp[i][j]:- 若
i > 0且s1[i-1] == s3[i+j-1],则检查dp[i-1][j](即当前字符来自s1)。 - 若
j > 0且s2[j-1] == s3[i+j-1],则检查dp[i][j-1](即当前字符来自s2)。 - 转移方程:
dp[i][j] = (s1[i-1] == s3[i+j-1] && dp[i-1][j]) || (s2[j-1] == s3[i+j-1] && dp[i][j-1])
- 若
- 初始状态:
-
边界处理
- 当
i=0时,只能从s2取字符:dp[0][j] = (s2[j-1] == s3[j-1]) && dp[0][j-1]。 - 当
j=0时,只能从s1取字符:dp[i][0] = (s1[i-1] == s3[i-1]) && dp[i-1][0]。
- 当
逐步计算示例
以 s1 = "aab", s2 = "dbbc", s3 = "aadbbbc" 为例(简化版,实际需匹配长度):
- 初始化
dp[0][0] = true。 - 第一行(仅用 s2):
dp[0][1]:s2[0]='d' vs s3[0]='a' → false。- 后续直接为 false,无需计算。
- 第一列(仅用 s1):
dp[1][0]:s1[0]='a' == s3[0]='a' 且dp[0][0]=true→ true。dp[2][0]:s1[1]='a' == s3[1]='a' 且dp[1][0]=true→ true。dp[3][0]:s1[2]='b' != s3[2]='d' → false。
- 计算
dp[1][1]:- 来自 s1:s1[0]='a' != s3[1]='a'?注意 s3 索引为 i+j-1=1,s3[1]='a',但 s1[0] 已用于
dp[0][1]?需重新核对:
实际应逐步填充表格,检查每个位置是否可能由上方或左方转移而来。
- 来自 s1:s1[0]='a' != s3[1]='a'?注意 s3 索引为 i+j-1=1,s3[1]='a',但 s1[0] 已用于
复杂度优化
- 时间复杂度:O(mn),其中 m、n 为 s1、s2 长度。
- 空间复杂度:可优化至 O(min(m,n)) 使用一维数组(滚动数组)。
关键点
- 状态定义中
i和j表示字符数,访问字符时需减1。 - 需先检查长度是否匹配,否则直接返回 false。
- 交错需保持原字符串顺序,因此只能从
s1或s2的头部依次取字符。