Problem
Given two strings str1
and str2
, return the shortest string that has both str1
and str2
as subsequences. If there are multiple valid strings, return any of them.
A string s
is a subsequence of string t
if deleting some number of characters from t
(possibly 0
) results in the string s
.
https://leetcode.com/problems/shortest-common-supersequence/
Example 1:
Input:
str1 = "abac", str2 = "cab"
Output:"cabac"
Explanation:
str1 = "abac"
is a subsequence of "cabac"
because we can delete the first"c"
.
str2 = "cab"
is a subsequence of"cabac"
because we can delete the last"ac"
.
The answer provided is the shortest such string that satisfies these properties.
Example 2:
Input:
str1 = "aaaaaaaa", str2 = "aaaaaaaa"
Output:"aaaaaaaa"
Constraints:
1 <= str1.length, str2.length <= 1000
str1
andstr2
consist of lowercase English letters.
Test Cases
1 | class Solution: |
1 | import pytest |
Thoughts
跟 1143. Longest Common Subsequence 本质上是同一个问题。想要公共超序列最短,就是要让公共子序列最长。设 str1 和 str2 的长度分别为 m 和 n,如果最长的公共子序列长度为 k,那么最短的公共超序列长度即为 k + (m - k) + (n - k) = m + n - k
。
先照搬 1143. Longest Common Subsequence 的代码,在最后会得到完整的 lcs(i, j)
表格。从 lcs(m, n)
开始就可以找出构造 LCS 的方式,而在 LCS 中把那些不相等的字符加上,就能得到最短公共超序列(SCS)。
对于 (i, j)
,如果 lcs(i, j) == lcs(i-1, j)
则说明 str1[i-1]
不属于 LCS,将其添加到 SCS,并继续看 (i-1, j)
;否则如果 lcs(i, j) == lcs(i, j-1)
则说明 str2[j-1]
不属于 LCS,将其添加到 SCS,并继续看 (i, j-1)
;否则(必然有 lcs(i, j) == lcs(i-1, j-1) + 1
)说明 str1[i-1] == str2[j-1]
属于 LCS,将其加入 LCS 和 SCS,并继续看 (i-1, j-1)
。
以 str1 = "abac"
、str2 = "cab"
为例,根据 lcs(i, j)
表格求出 LCS 和 SCS 的过程如下图示:
按上边提到的规则,找到从 (m, n)
到 (0, 0)
的路径。对于除了终点的任何一个格子,向上走的取所在行对应的字符(取自 str1),向左走的取所在列对应的字符(取自 str2),斜向左上走的说明所在行和列的字符相同。
空间复杂度 O(m * n)
,时间复杂度 O(m * n)
。
Code
1 | class Solution: |