交错字符串
Tips
题目类型: Dynamic Programming
题目
给定三个字符串 s1, s2, s3, 请你帮忙验证 s3 是否是由 s1 和 s2 交错组成的. 要求使用 O(s2.length) 额外的内存空间来解决.
两个字符串 s 和 t 交错的定义与过程如下, 其中每个字符串都会被分割成若干非空子字符串:
s = s1 + s2 + ... + snt = t1 + t2 + ... + tm|n - m| <= 1- 交错是
s1 + t1 + s2 + t2 + s3 + t3 + ...或者t1 + s1 + t2 + s2 + t3 + s3 + ...
注意: a + b 意味着字符串 a 和 b 连接.
提示:
0 <= s1.length, s2.length <= 1000 <= s3.length <= 200s1,s2, 和s3都由小写英文字母组成
示例

输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出: true
题解
这道题如果能看出来可以转换成下面这种形态就好办了. 它就是 64. 最小路径和 的变种题, 即每次只能往右或往下选择字符, 是否存在路径可以从左上角到右下角.

- JavaScript
- Rust
于是可定义二维数组 dp, dp[i][j] 代表 s1 前 i 个字符与 s2 前 j 个字符拼接成 s3 的 i + j 个字符, 也就是存在目标路径能够到达 i, j.
状态转移方程:
dp[0][0] = true- 第一列只能一直往下走, 此时如果
s1[i - 1] === s3[i - 1], 有dp[i][0] = true - 第一行只能一直往右走, 此时如果
s2[j - 1] === s3[j - 1], 有dp[0][j] = true - 其他情况, 到达
dp[i][j]可能由dp[i - 1][j]到达, 也可能由dp[i][j - 1]到达, 因此有dp[i][j] = (dp[i - 1][j] && s1[i - 1] === s3[i + j - 1]) || (dp[i][j - 1] && s2[j - 1] === s3[i + j - 1])
/**
* @param {string} s1
* @param {string} s2
* @param {string} s3
* @return {boolean}
*/
var isInterleave = function (s1, s2, s3) {
const m = s1.length
const n = s2.length
if (m + n !== s3.length) return false
const dp = new Array(m + 1)
.fill(false)
.map(() => new Array(n + 1).fill(false))
dp[0][0] = true
for (let i = 1; i <= m && s1[i - 1] === s3[i - 1]; i++) dp[i][0] = true
for (let j = 1; j <= n && s2[j - 1] === s3[j - 1]; j++) dp[0][j] = true
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
dp[i][j] =
(dp[i - 1][j] && s1[i - 1] === s3[i + j - 1]) ||
(dp[i][j - 1] && s2[j - 1] === s3[i + j - 1])
}
}
return dp[m][n]
}
pub fn is_interleave(s1: String, s2: String, s3: String) -> bool {
let (s1, s2, s3) = (s1.as_bytes(), s2.as_bytes(), s3.as_bytes());
let (n1, n2, n3) = (s1.len(), s2.len(), s3.len());
if n1 + n2 != n3 { return false; }
let mut dp = vec![vec![false; n2 + 1]; n1 + 1];
dp[0][0] = true;
for i in 1..=n1 {
match s1[i - 1] == s3[i - 1] {
true => dp[i][0] = true,
false => break,
}
}
for j in 1..=n2 {
match s2[j - 1] == s3[j - 1] {
true => dp[0][j] = true,
false => break,
}
}
for i in 1..=n1 {
for j in 1..=n2 {
dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i + j - 1])
|| (dp[i][j - 1] && s2[j - 1] == s3[i + j - 1]);
}
}
dp[n1][n2]
}