Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b5f5d13

Browse files
✨feat: add 1092
1 parent b5ccb87 commit b5f5d13

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)

AltStyle によって変換されたページ (->オリジナル) /