97.Interleaving String
===
###### tags: `Medium` `String` `DP`
[97. Interleaving String](https://leetcode.com/problems/interleaving-string/)
### 題目描述
Given strings `s1`, `s2`, and `s3`, find whether `s3` is formed by an **interleaving** of `s1` and `s2`.
An **interleaving** of two strings `s` and `t` is a configuration where `s` and `t` are divided into `n` and `m` substrings respectively, such that:
* `s = s1 + s2 + ... + sn`
* `t = t1 + t2 + ... + tm`
* `|n - m| <= 1`
* The **interleaving** is `s1 + t1 + s2 + t2 + s3 + t3 + ...` or `t1 + s1 + t2 + s2 + t3 + s3 + ...`
**Note:** `a + b` is the concatenation of strings `a` and `b`.
### 範例
**Example 1:**
![](https://assets.leetcode.com/uploads/2020/09/02/interleave.jpg)
```
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
Output: true
Explanation: One way to obtain s3 is:
Split s1 into s1 = "aa" + "bc" + "c", and s2 into s2 = "dbbc" + "a".
Interleaving the two splits, we get "aa" + "dbbc" + "bc" + "a" + "c" = "aadbbcbcac".
Since s3 can be obtained by interleaving s1 and s2, we return true.
```
**Example 2:**
```
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
Output: false
Explanation: Notice how it is impossible to interleave s2 with any other string to obtain s3.
```
**Example 3:**
```
Input: s1 = "", s2 = "", s3 = ""
Output: true
```
**Constraints**:
* 0 <= `s1.length`, `s2.length` <= 100
* 0 <= `s3.length` <= 200
* `s1`, `s2`, and `s3` consist of lowercase English letters.
**Follow up:** Could you solve it using only `O(s2.length)` additional memory space?
### 解答
#### TypeScript
`dp[i][j]` 表示 `s1` 的前 `i` 個字元和 `s2` 的前 `j` 個字元是否可以交錯組合成 `s3` 的前 `i + j` 個字元。
從下面兩個方向達到目前狀態 `(i,j)`:
1. 從 `(i - 1, j)` 轉移:
- 如果 `dp[i - 1][j] == true`,代表著 `s1` 的前 `i - 1` 個字元和 `s2` 的前 `j` 個字元可以交錯組合成 `s3` 的前 `i + j - 1` 個字元。
- 然後我們只需檢查 `s1[i - 1]` 是否等於 `s3[i + j - 1]`。如果相等,則 `dp[i][j]` 也為 `true`
2. 從 `i, j - 1` 轉移:
- 如果 `dp[i, j - 1] == true`,代表著 `s1` 的前 `i` 個字元和 `s2` 的前 `j - 1` 個字元可以交錯組合成 `s3` 的前 `i + j - 1` 個字元。
- 一樣檢查 `s2[j - 1]` 是否等於 `s3[i + j - 1]`。如果相等,則 `dp[i][j]` 也為 `true`
```typescript
function isInterleave(s1: string, s2: string, s3: string): boolean {
if (s1.length + s2.length !== s3.length) return false;
const dp: boolean[][] = new Array(s1.length + 1)
.fill(0)
.map(() => new Array(s2.length + 1).fill(false));
dp[0][0] = true;
// s2 = ''
for (let i = 1; i <= s1.length; i++) {
dp[i][0] = dp[i - 1][0] && s1[i - 1] === s3[i - 1];
}
// s1 = ''
for (let j = 1; j <= s2.length; j++) {
dp[0][j] = dp[0][j - 1] && s2[j - 1] === s3[j - 1];
}
for (let i = 1; i <= s1.length; i++) {
for (let j = 1; j <= s2.length; 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[s1.length][s2.length];
}
```
> [name=sheep][time=Fri, 25 Aug 2023]
#### Python
```python=
class Solution:
def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
if len(s1) + len(s2) != len(s3):
return False
@cache
def dfs(i, j):
if i == 0 and j == 0:
return True
if i == 0:
return s2[j - 1] == s3[j - 1] and dfs(i, j - 1)
if j == 0:
return s1[i - 1] == s3[i - 1] and dfs(i - 1, j)
return (s1[i - 1] == s3[i + j - 1] and dfs(i - 1, j)) \
or (s2[j - 1] == s3[i + j - 1] and dfs(i, j - 1))
return dfs(len(s1), len(s2))
```
> [name=Yen-Chi Chen][time=Fri, Aug 25, 2023]
### Reference
[回到題目列表](https://marsgoat.github.io/XNnote/coding/leetcodeEveryDay.html)