目录

1520:最多的不重叠子字符串(2362 分)

力扣第 198 场周赛第 3 题

题目

给你一个只包含小写字母的字符串 s ,你需要找到 s 中最多数目的非空子字符串,满足如下条件:

  1. 这些字符串之间互不重叠,也就是说对于任意两个子字符串 s[i..j]s[x..y] ,要么 j < x 要么 i > y
  2. 如果一个子字符串包含字符 char ,那么 s 中所有 char 字符都应该在这个子字符串中。

请你找到满足上述条件的最多子字符串数目。如果有多个解法有相同的子字符串数目,请返回这些子字符串总长度最小的一个解。可以证明最小总长度解是唯一的。

请注意,你可以以 任意 顺序返回最优解的子字符串。

示例 1:

输入:s = "adefaddaccc"
输出:["e","f","ccc"]
解释:下面为所有满足第二个条件的子字符串:
[
"adefaddaccc"
"adefadda",
"ef",
"e",
"f",
"ccc",
]
如果我们选择第一个字符串,那么我们无法再选择其他任何字符串,所以答案为 1 。如果我们选择 "adefadda" ,剩下子字符串中我们只可以选择 "ccc" ,它是唯一不重叠的子字符串,所以答案为 2 。同时我们可以发现,选择 "ef" 不是最优的,因为它可以被拆分成 2 个子字符串。所以最优解是选择 ["e","f","ccc"] ,答案为 3 。不存在别的相同数目子字符串解。

示例 2:

输入:s = "abbaccd"
输出:["d","bb","cc"]
解释:注意到解 ["d","abba","cc"] 答案也为 3 ,但它不是最优解,因为它的总长度更长。

提示:

  • 1 <= s.length <= 10^5
  • s 只包含小写英文字母。

相似问题:

分析

  • 先得到每个字母的下标列表
  • 根据不同字母的区间包含关系,可以建有向图
  • 有向图中,从某个字母出发能访问的所有字母的区间的并即是一个有效的子串区间
  • 从至多26个有效区间中选最多的不重叠个数,即是问题 0435

解答

 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
28
29
30
31
32
33
34
35
36
class Solution:
    def maxNumOfSubstrings(self, s: str) -> List[str]:
        d = defaultdict(list)
        for i,c in enumerate(s):
            d[c].append(i)
        g = defaultdict(list)
        for u in d:
            l,r = d[u][0], d[u][-1]
            for v,A in d.items():
                if v!=u:
                    i = bisect_left(A,l)
                    if i<len(A) and A[i]<=r:
                        g[u].append(v)
        def bfs(c):
            l,r = inf,-inf
            dq = deque([c])
            vis = {c}
            while dq:
                u = dq.popleft()
                l = min(l,d[u][0])
                r = max(r,d[u][-1])
                for v in g[u]:
                    if v not in vis:
                        vis.add(v)
                        dq.append(v)
            return l,r

        ans = [bfs(u) for u in d]
        ans.sort(key=lambda x: x[1])
        res = []
        pre = -1
        for l, r in ans:
            if l>pre:
                res.append(s[l:r+1])
                pre = r
        return res

111 ms