目录

0943:最短超级串(2185 分)

力扣第 111 场周赛第 4 题

题目

给定一个字符串数组 words,找到以 words 中每个字符串作为子字符串的最短字符串。如果有多个有效最短字符串满足题目条件,返回其中 任意一个 即可。

我们可以假设 words 中没有字符串是 words 中另一个字符串的子字符串。

示例 1:

输入:words = ["alex","loves","leetcode"]
输出:"alexlovesleetcode"
解释:"alex","loves","leetcode" 的所有排列都会被接受。

示例 2:

输入:words = ["catg","ctaagt","gcta","ttca","atgcatc"]
输出:"gctaagttcatgcatc"

提示:

  • 1 <= words.length <= 12
  • 1 <= words[i].length <= 20
  • words[i] 由小写英文字母组成
  • words 中的所有字符串 互不相同

相似问题:

分析

#1

  • 按结尾选哪个字符串即可递归
  • 计算两个字符串重叠长度,也可记忆化
  • 为了方便,可以令 dfs 直接返回最短字符串
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution:
    def shortestSuperstring(self, words: List[str]) -> str:
        @cache
        def cal(a,b):
            return next(i for i in range(len(b),-1,-1) if a.endswith(b[:i]))
        @cache
        def dfs(A,a):
            if len(A)==1:
                return a
            B = tuple(set(A)-{a})
            return min([dfs(B,b)+a[cal(b,a):] for b in B],key=len)
        return min([dfs(tuple(words),a) for a in words],key=len)

1299 ms

#2

  • 更通用的方法是先递推最短长度,再根据转移过程得到对应的字符串
  • 令 f[st][i] 代表集合 st 且以 i 结尾的最短长度
  • 预处理 g[i][j] 代表 words[i] 接 words[j] 的重叠长度
  • 令 rf[st][i]=j 代表 f[st][i] 由 f[st^1«i][j] 转移而来

解答

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution:
    def shortestSuperstring(self, words: List[str]) -> str:
        def cal(a,b):
            return next(i for i in range(len(b),-1,-1) if a.endswith(b[:i]))
        n = len(words)
        g = [[cal(a,b) for b in words] for a in words]
        f = [[inf]*n for _ in range(1<<n)]
        rf = [[0]*n for _ in range(1<<n)]
        for st in range(1,1<<n):
            for i in range(n):
                if st>>i&1:
                    w = len(words[i])
                    st2 = st^1<<i
                    if not st2:
                        f[st][i] = w
                    else:
                        j = min(range(n),key=lambda j:f[st2][j]+w-g[j][i])
                        f[st][i] = f[st2][j]+w-g[j][i]
                        rf[st][i] = j
        st = (1<<n)-1
        i = min(range(n),key=lambda i:f[-1][i])
        res = words[i]
        while st.bit_count()>1:
            j = rf[st][i]
            res = words[j]+res[g[j][i]:]
            st,i = st^1<<i,j
        return res

587 ms