Skip to content

Commit 9e4dc46

Browse files
Merge pull request #679 from SharingSource/ac_oier
✨feat: add 1092
2 parents 9e0917e + b5f5d13 commit 9e4dc46

File tree

4 files changed

+175
-0
lines changed

4 files changed

+175
-0
lines changed

Index/双指针.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
| [1021. 删除最外层的括号](https://leetcode.cn/problems/remove-outermost-parentheses/) | [LeetCode 题解链接](https://leetcode.cn/problems/remove-outermost-parentheses/solution/by-ac_oier-jmxi/) | 简单 | 🤩🤩🤩🤩 |
4848
| [1052. 爱生气的书店老板](https://leetcode-cn.com/problems/grumpy-bookstore-owner/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/grumpy-bookstore-owner/solution/hua-dong-chuang-kou-luo-ti-by-ac_oier-nunu/) | 中等 | 🤩🤩🤩 |
4949
| [1089. 复写零](https://leetcode.cn/problems/duplicate-zeros/) | [LeetCode 题解链接](https://leetcode.cn/problems/duplicate-zeros/solution/by-ac_oier-zivq/) | 简单 | 🤩🤩🤩🤩 |
50+
| [1092. 最短公共超序列](https://leetcode.cn/problems/shortest-common-supersequence/) | [LeetCode 题解链接](https://leetcode.cn/problems/shortest-common-supersequence/solution/by-ac_oier-s346/) | 困难 | 🤩🤩🤩 |
5051
| [1221. 分割平衡字符串](https://leetcode-cn.com/problems/split-a-string-in-balanced-strings/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/split-a-string-in-balanced-strings/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-wumnk/) | 简单 | 🤩🤩🤩🤩 |
5152
| [1332. 删除回文子序列](https://leetcode-cn.com/problems/remove-palindromic-subsequences/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/remove-palindromic-subsequences/solution/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-0zwn/) | 简单 | 🤩🤩🤩🤩 |
5253
| [1417. 重新格式化字符串](https://leetcode.cn/problems/reformat-the-string/) | [LeetCode 题解链接](https://leetcode.cn/problems/reformat-the-string/solution/by-ac_oier-uk8z/) | 简单 | 🤩🤩🤩🤩 |

Index/序列 DP.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
| [926. 将字符串翻转到单调递增](https://leetcode.cn/problems/flip-string-to-monotone-increasing/) | [LeetCode 题解链接](https://leetcode.cn/problems/flip-string-to-monotone-increasing/solution/by-ac_oier-h0we/) | 中等 | 🤩🤩🤩🤩🤩 |
1818
| [978. 最长湍流子数组](https://leetcode-cn.com/problems/longest-turbulent-subarray/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/longest-turbulent-subarray/solution/xiang-jie-dong-tai-gui-hua-ru-he-cai-dp-3spgj/) | 中等 | 🤩🤩🤩 |
1919
| [1035. 不相交的线](https://leetcode-cn.com/problems/uncrossed-lines/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/uncrossed-lines/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-bkaas/) | 中等 | 🤩🤩🤩🤩 |
20+
| [1092. 最短公共超序列](https://leetcode.cn/problems/shortest-common-supersequence/) | [LeetCode 题解链接](https://leetcode.cn/problems/shortest-common-supersequence/solution/by-ac_oier-s346/) | 困难 | 🤩🤩🤩🤩 |
2021
| [1143. 最长公共子序列](https://leetcode-cn.com/problems/longest-common-subsequence/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/longest-common-subsequence/solution/gong-shui-san-xie-zui-chang-gong-gong-zi-xq0h/) | 中等 | 🤩🤩🤩🤩 |
2122
| [1218. 最长定差子序列](https://leetcode-cn.com/problems/longest-arithmetic-subsequence-of-given-difference/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/longest-arithmetic-subsequence-of-given-difference/solution/gong-shui-san-xie-jie-he-tan-xin-de-zhua-dj1k/) | 中等 | 🤩🤩🤩🤩🤩 |
2223
| [1473. 粉刷房子 III](https://leetcode-cn.com/problems/paint-house-iii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/paint-house-iii/solution/gong-shui-san-xie-san-wei-dong-tai-gui-h-ud7m/) | 困难 | 🤩🤩🤩🤩 |

Index/构造.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
| [899. 有序队列](https://leetcode.cn/problems/orderly-queue/) | [LeetCode 题解链接](https://leetcode.cn/problems/orderly-queue/solution/by-ac_oier-443m/) | 困难 | 🤩🤩🤩 |
99
| [942. 增减字符串匹配](https://leetcode.cn/problems/di-string-match/) | [LeetCode 题解链接](https://leetcode.cn/problems/di-string-match/solution/by-ac_oier-pvjk/) | 简单 | 🤩🤩🤩🤩🤩 |
1010
| [961. 在长度 2N 的数组中找出重复 N 次的元素](https://leetcode.cn/problems/n-repeated-element-in-size-2n-array/) | [LeetCode 题解链接](https://leetcode.cn/problems/n-repeated-element-in-size-2n-array/solution/by-ac_oier-bslq/) | 简单 | 🤩🤩🤩🤩 |
11+
| [1092. 最短公共超序列](https://leetcode.cn/problems/shortest-common-supersequence/) | [LeetCode 题解链接](https://leetcode.cn/problems/shortest-common-supersequence/solution/by-ac_oier-s346/) | 困难 | 🤩🤩🤩🤩 |
1112
| [1260. 二维网格迁移](https://leetcode.cn/problems/shift-2d-grid/) | [LeetCode 题解链接](https://leetcode.cn/problems/shift-2d-grid/solution/by-ac_oier-1blt/) | 简单 | 🤩🤩🤩🤩 |
1213
| [1537. 最大得分](https://leetcode.cn/problems/get-the-maximum-score/) | [LeetCode 题解链接](https://leetcode.cn/problems/get-the-maximum-score/solution/by-ac_oier-ht78/) | 困难 | 🤩🤩🤩🤩 |
1314
| [1719. 重构一棵树的方案数](https://leetcode-cn.com/problems/number-of-ways-to-reconstruct-a-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-ways-to-reconstruct-a-tree/solution/gong-shui-san-xie-gou-zao-yan-zheng-he-f-q6fc/) | 困难 | 🤩🤩 |
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[1092. 最短公共超序列](https://leetcode.cn/problems/shortest-common-supersequence/solution/by-ac_oier-s346/)** ,难度为 **困难**
4+
5+
Tag : 「序列 DP」、「LCS」、「最长上升子序列」、「动态规划」、「构造」、「双指针」
6+
7+
8+
9+
给出两个字符串 `str1` 和 `str2`,返回同时以 `str1` 和 `str2` 作为子序列的最短字符串。如果答案不止一个,则可以返回满足条件的任意一个答案。
10+
11+
(如果从字符串 `T` 中删除一些字符(也可能不删除,并且选出的这些字符可以位于 `T` 中的 任意位置),可以得到字符串 `S`,那么 `S` 就是 `T` 的子序列)
12+
13+
示例:
14+
```
15+
输入:str1 = "abac", str2 = "cab"
16+
17+
输出:"cabac"
18+
19+
解释:
20+
str1 = "abac" 是 "cabac" 的一个子串,因为我们可以删去 "cabac" 的第一个 "c"得到 "abac"。
21+
str2 = "cab" 是 "cabac" 的一个子串,因为我们可以删去 "cabac" 末尾的 "ac" 得到 "cab"。
22+
最终我们给出的答案是满足上述属性的最短字符串。
23+
```
24+
25+
提示:
26+
* $1 <= str1.length, str2.length <= 1000$
27+
* `str1` 和 `str2` 都由小写英文字母组成。
28+
29+
---
30+
31+
### LCS 求具体方案 + 构造
32+
33+
为了方便,我们令 `str1``s1``str2``s2`,并将两者长度记为 $n$ 和 $m$。
34+
35+
容易想到最终的方案必然是由三部分组成:两字符串的公共子序列(且必然是最长公共子序列)+ 两者特有的字符部分。
36+
37+
基于此,我们可以先使用对两者求 `LCS`,并在求具体方案时遵循:属于最长公共子序列的字符只添加一次,而特有于 `s1``s2` 的字符则独自添加一次。
38+
39+
求解 `LCS` 部分我们定义 **$f[i][j]$ 代表考虑 $s1$ 的前 $i$ 个字符、考虑 $s2$ 的前 $j$ 的字符,形成的最长公共子序列长度(为了方便,令下标从 $1$ 开始)。**
40+
41+
当有了「状态定义」之后,基本上「转移方程」就是呼之欲出:
42+
43+
* `s1[i]==s2[j]` : $f[i][j]=f[i-1][j-1]+1$。代表**必然使用 $s1[i]$ 与 $s2[j]$ 时** `LCS` 的长度。
44+
* `s1[i]!=s2[j]` : $f[i][j]=max(f[i-1][j], f[i][j-1])$。代表**必然不使用 $s1[i]$(但可能使用$s2[j]$)时****必然不使用 $s2[j]$(但可能使用$s1[i]$)时** `LCS` 的长度。
45+
46+
> **不了解 LCS 的同学可以看前置 🧀 : [LCS 模板题](https://mp.weixin.qq.com/s?__biz=MzU4NDE3MTEyMA==&mid=2247492097&idx=1&sn=f51f29d86df809d8ac43a40a1369b3d6)**
47+
48+
当预处理出动规数组 `f` 之后,我们使用「双指针」和「通用 `DP` 求具体方案」的做法进行构造:使用 `i` 变量指向 `s1` 的尾部(即起始有 $i = n$),使用 `j` 变量指向 `s2` 的尾部(即起始有 $j = m$),根据 `i``j` 当前所在位置以及 $f[i][j]$ 从何值转移而来:
49+
50+
1.`i``j` 其一走完(`i = 0``j = 0`),将剩余字符追加到答案中;
51+
2. 当 $f[i][j] = f[i - 1][j - 1] + 1$ 且 $s1[i] = s2[j]$ 时(可简化为 $s1[i] = s2[j]$ 判断),此时 `i` 指向的字符和 `j` 指向的字符为相同,且为 `LCS` 中的字符,将其追加到具体方案,并让 `i``j` 同时后移;
52+
3. 当 $f[i][j] = f[i - 1][j]$,将 `s1[i]` 追加到答案中,令 `i` 后移;
53+
4. 当 $f[i][j] = f[i][j - 1]$,将 `s2[j]` 追加到答案中,令 `j` 后移。
54+
55+
当条件 `3``4` 同时满足时,由于只需要输出任一具体方案,我们任取其一即可。
56+
57+
最后,由于我们是从后往前进行构造,在返回时需要再进行一次翻转。
58+
59+
Java 代码:
60+
```Java
61+
class Solution {
62+
public String shortestCommonSupersequence(String str1, String str2) {
63+
int n = str1.length(), m = str2.length();
64+
str1 = " " + str1; str2 = " " + str2;
65+
char[] s1 = str1.toCharArray(), s2 = str2.toCharArray();
66+
int[][] f = new int[n + 10][m + 10];
67+
for (int i = 1; i <= n; i++) {
68+
for (int j = 1; j <= m; j++) {
69+
if (s1[i] == s2[j]) f[i][j] = f[i - 1][j - 1] + 1;
70+
else f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
71+
}
72+
}
73+
StringBuilder sb = new StringBuilder();
74+
int i = n, j = m;
75+
while (i > 0 || j > 0) {
76+
if (i == 0) sb.append(s2[j--]);
77+
else if (j == 0) sb.append(s1[i--]);
78+
else {
79+
if (s1[i] == s2[j]) {
80+
sb.append(s1[i]);
81+
i--; j--;
82+
} else if (f[i][j] == f[i - 1][j]) {
83+
sb.append(s1[i--]);
84+
} else {
85+
sb.append(s2[j--]);
86+
}
87+
}
88+
}
89+
return sb.reverse().toString();
90+
}
91+
}
92+
```
93+
TypeScript 代码:
94+
```TypeScript
95+
function shortestCommonSupersequence(s1: string, s2: string): string {
96+
const n = s1.length, m = s2.length
97+
s1 = " " + s1; s2 = " " + s2
98+
const f = new Array<Array<number>>()
99+
for (let i = 0; i < n + 10; i++) f.push(new Array<number>(m + 10).fill(0))
100+
for (let i = 1; i <= n; i++) {
101+
for (let j = 1; j <= m; j++) {
102+
if (s1[i] == s2[j]) f[i][j] = f[i - 1][j - 1] + 1
103+
else f[i][j] = Math.max(f[i - 1][j], f[i][j - 1])
104+
}
105+
}
106+
let ans = ""
107+
let i = n, j = m
108+
while (i > 0 || j > 0) {
109+
if (i == 0) ans += s2[j--]
110+
else if (j == 0) ans += s1[i--]
111+
else {
112+
if (s1[i] == s2[j]) {
113+
ans += s1[i]
114+
i--; j--
115+
} else if (f[i][j] == f[i - 1][j]) {
116+
ans += s1[i--]
117+
} else {
118+
ans += s2[j--]
119+
}
120+
}
121+
}
122+
return ans.split('').reverse().join('')
123+
};
124+
```
125+
Python 代码:
126+
```Python
127+
class Solution:
128+
def shortestCommonSupersequence(self, s1: str, s2: str) -> str:
129+
n, m = len(s1), len(s2)
130+
s1 = " " + s1
131+
s2 = " " + s2
132+
f = [[0] * (m + 10) for _ in range(n + 10)]
133+
for i in range(1, n + 1):
134+
for j in range(1, m + 1):
135+
f[i][j] = f[i - 1][j - 1] + 1 if s1[i] == s2[j] else max(f[i - 1][j], f[i][j - 1])
136+
ans = ""
137+
i, j = n, m
138+
while i > 0 or j > 0:
139+
if i == 0:
140+
ans += s2[j]
141+
j -= 1
142+
elif j == 0:
143+
ans += s1[i]
144+
i -= 1
145+
else:
146+
if s1[i] == s2[j]:
147+
ans += s1[i]
148+
i -= 1
149+
j -= 1
150+
elif f[i][j] == f[i - 1][j]:
151+
ans += s1[i]
152+
i -= 1
153+
else:
154+
ans += s2[j]
155+
j -= 1
156+
return ans[::-1]
157+
```
158+
* 时间复杂度:`LCS` 复杂度为 $O(n \times m)$;构造答案复杂度为 $O(n \times m)$。整体复杂度为 $O(n \times m)$
159+
* 空间复杂度:$O(n \times m)$
160+
161+
---
162+
163+
### 最后
164+
165+
这是我们「刷穿 LeetCode」系列文章的第 `No.1092` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
166+
167+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
168+
169+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
170+
171+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
172+

0 commit comments

Comments
 (0)