带限制的字符串交织问题
题目描述
给定三个字符串 s1、s2 和 s3,以及一个整数 k。判断是否可以通过交替选择 s1 和 s2 的子序列(每个子序列长度至少为1,且每次选择的子序列长度不能超过 k),拼接形成 s3。要求每次选择的子序列必须连续从当前字符串中取出,且每次选择后必须切换到另一个字符串继续取。如果能够形成 s3,返回 true,否则返回 false。
示例
输入:s1 = "abc", s2 = "def", s3 = "adbecf", k = 2
输出:true
解释:选择顺序为:从s1取"ab"(长度2),从s2取"de"(长度2),从s1取"c"(长度1),从s2取"f"(长度1)。每次选择长度均不超过k=2,且最终拼接成s3。
解题过程
1. 问题分析
- 目标:用s1和s2的子序列交替拼接成s3,每次选取的子序列长度在[1, k]之间。
- 关键约束:每次选择后必须切换字符串,且选取的子序列必须连续。
- 难点:需要同时跟踪当前在s1还是s2中选取、已匹配的s3位置、以及当前连续选取的长度。
2. 状态定义
定义五维DP数组:
dp[i][j][t][x][l] 表示当前已匹配s1的前i个字符、s2的前j个字符、s3的前t个字符,当前正在从字符串x(x=0表示s1,x=1表示s2)中选取子序列,且当前连续选取的长度为l时,是否可行。
- 状态值:true或false。
3. 状态转移方程
分为两种情况:
(1) 继续从当前字符串选取(延长当前子序列):
若当前在s1中选取(x=0),则需满足:
i < len(s1)且t < len(s3)且s1[i] == s3[t]- 当前连续长度l < k
转移:dp[i+1][j][t+1][0][l+1] |= dp[i][j][t][0][l]
若当前在s2中选取(x=1),条件类似:
j < len(s2)且t < len(s3)且s2[j] == s3[t]- l < k
转移:dp[i][j+1][t+1][1][l+1] |= dp[i][j][t][1][l]
(2) 切换到另一个字符串开始新子序列:
若当前在s1中(x=0),可切换到s2(x=1),新子序列长度从1开始:
条件:当前已选取的子序列长度l ≥ 1(保证每次选取非空)
转移:dp[i][j][t][1][1] |= dp[i][j][t][0][l]
(注意:切换时i、j、t不变,因为尚未消耗新字符)
若当前在s2中(x=1),切换到s1类似:
dp[i][j][t][0][1] |= dp[i][j][t][1][l]
4. 初始化
可以从s1或s2开始:
- 从s1开始:
dp[0][0][0][0][0] = true(未选任何字符时,长度为0) - 从s2开始:
dp[0][0][0][1][0] = true
5. 最终状态
当 t == len(s3) 且当前连续长度l ≥ 1(最后一段非空)时,如果 dp[i][j][t][x][l] 为true,则返回true。
即要求s3全部匹配完成,且最后一段选取是有效的。
6. 复杂度优化
五维DP可能开销较大。可减少一维:
- 将状态定义为
dp[i][j][t][x],其中x表示当前正在选取的字符串(0/1),但额外记录当前连续长度l可能需遍历1到k。 - 实际实现时,可用l作为隐含条件,在转移时判断。
总结
本题通过五维DP精确刻画了交替选取、长度限制的条件。核心是在匹配字符的同时,控制子序列长度和切换时机。