|
| 1 | +# 题目地址(1297. 子串的最大出现次数) |
| 2 | + |
| 3 | +https://leetcode-cn.com/problems/maximum-number-of-occurrences-of-a-substring |
| 4 | + |
| 5 | +## 题目描述 |
| 6 | + |
| 7 | +``` |
| 8 | +给你一个字符串 s ,请你返回满足以下条件且出现次数最大的 任意 子串的出现次数: |
| 9 | +
|
| 10 | +子串中不同字母的数目必须小于等于 maxLetters 。 |
| 11 | +子串的长度必须大于等于 minSize 且小于等于 maxSize 。 |
| 12 | +
|
| 13 | +
|
| 14 | +示例 1: |
| 15 | +
|
| 16 | +输入:s = "aababcaab", maxLetters = 2, minSize = 3, maxSize = 4 |
| 17 | +输出:2 |
| 18 | +解释:子串 "aab" 在原字符串中出现了 2 次。 |
| 19 | +它满足所有的要求:2 个不同的字母,长度为 3 (在 minSize 和 maxSize 范围内)。 |
| 20 | +示例 2: |
| 21 | +
|
| 22 | +输入:s = "aaaa", maxLetters = 1, minSize = 3, maxSize = 3 |
| 23 | +输出:2 |
| 24 | +解释:子串 "aaa" 在原字符串中出现了 2 次,且它们有重叠部分。 |
| 25 | +示例 3: |
| 26 | +
|
| 27 | +输入:s = "aabcabcab", maxLetters = 2, minSize = 2, maxSize = 3 |
| 28 | +输出:3 |
| 29 | +示例 4: |
| 30 | +
|
| 31 | +输入:s = "abcde", maxLetters = 2, minSize = 3, maxSize = 3 |
| 32 | +输出:0 |
| 33 | +
|
| 34 | +
|
| 35 | +提示: |
| 36 | +
|
| 37 | +1 <= s.length <= 10^5 |
| 38 | +1 <= maxLetters <= 26 |
| 39 | +1 <= minSize <= maxSize <= min(26, s.length) |
| 40 | +s 只包含小写英文字母。 |
| 41 | +``` |
| 42 | + |
| 43 | +## 暴力法 |
| 44 | + |
| 45 | +题目给的数据量不是很大,为 1 <= maxLetters <= 26,我们试一下暴力法。 |
| 46 | + |
| 47 | +### 思路 |
| 48 | + |
| 49 | +暴力法如下: |
| 50 | + |
| 51 | +- 先找出所有满足长度大于等于 minSize 且小于等于 maxSize 的所有子串。(平方的复杂度) |
| 52 | +- 对于 maxLetter 满足题意的子串,我们统计其出现次数。时间复杂度为 O(k),其中 k 为子串长度 |
| 53 | +- 返回最大的出现次数 |
| 54 | + |
| 55 | +### 代码 |
| 56 | + |
| 57 | +Pythpn Code: |
| 58 | + |
| 59 | +```python |
| 60 | +class Solution: |
| 61 | + def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int: |
| 62 | + n = len(s) |
| 63 | + letters = set() |
| 64 | + cnts = dict() |
| 65 | + res = 0 |
| 66 | + for i in range(n - minSize + 1): |
| 67 | + length = minSize |
| 68 | + while i + length <= n and length <= maxSize: |
| 69 | + t = s[i:i + length] |
| 70 | + for c in t: |
| 71 | + if len(letters) > maxLetters: |
| 72 | + break |
| 73 | + letters.add(c) |
| 74 | + if len(letters) <= maxLetters: |
| 75 | + cnts[t] = cnts.get(t, 0) + 1 |
| 76 | + res = max(res, cnts[t]) |
| 77 | + letters.clear() |
| 78 | + length += 1 |
| 79 | + return res |
| 80 | +``` |
| 81 | + |
| 82 | +上述代码会超时。我们来利用剪枝来优化。 |
| 83 | + |
| 84 | +## 剪枝 |
| 85 | + |
| 86 | +### 思路 |
| 87 | + |
| 88 | +还是暴力法的思路,不过我们在此基础上进行一些优化。首先我们需要仔细阅读题目,如果你足够细心或者足够有经验,可能会发现其实题目中 maxSize 没有任何用处,属于干扰信息。 |
| 89 | + |
| 90 | +也就是说我们没有必要统计`长度大于等于 minSize 且小于等于 maxSize 的所有子串`,而是统计长度为 minSize 的所有字串即可。原因是,如果一个大于 minSize 长度的字串若是满足条件,那么该子串其中必定有至少一个长度为 minSize 的字串满足条件。因此一个大于 minSize 长度的字串出现了 n 次,那么该子串其中必定有一个长度为 minSize 的子串出现了 n 次。 |
| 91 | + |
| 92 | +### 代码 |
| 93 | + |
| 94 | +代码支持 Python3,Java: |
| 95 | + |
| 96 | +Python Code: |
| 97 | + |
| 98 | +```python |
| 99 | + def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int: |
| 100 | + counter, res = {}, 0 |
| 101 | + for i in range(0, len(s) - minSize + 1): |
| 102 | + sub = s[i : i + minSize] |
| 103 | + if len(set(sub)) <= maxLetters: |
| 104 | + counter[sub] = counter.get(sub, 0) + 1 |
| 105 | + res = max(res, counter[sub]) |
| 106 | + return res; |
| 107 | + |
| 108 | +# @lc code=end |
| 109 | +``` |
| 110 | + |
| 111 | +Java Code: |
| 112 | + |
| 113 | +```java |
| 114 | + public int maxFreq(String s, int maxLetters, int minSize, int maxSize) { |
| 115 | + Map<String, Integer> counter = new HashMap<>(); |
| 116 | + int res = 0; |
| 117 | + for (int i = 0; i < s.length() - minSize + 1; i++) { |
| 118 | + String substr = s.substring(i, i + minSize); |
| 119 | + if (checkNum(substr, maxLetters)) { |
| 120 | + int newVal = counter.getOrDefault(substr, 0) + 1; |
| 121 | + counter.put(substr, newVal); |
| 122 | + res = Math.max(res, newVal); |
| 123 | + } |
| 124 | + } |
| 125 | + return res; |
| 126 | +} |
| 127 | +public boolean checkNum(String substr, int maxLetters) { |
| 128 | + Set<Character> set = new HashSet<>(); |
| 129 | + for (int i = 0; i < substr.length(); i++) |
| 130 | + set.add(substr.charAt(i)); |
| 131 | + return set.size() <= maxLetters; |
| 132 | +} |
| 133 | + |
| 134 | +``` |
| 135 | + |
| 136 | +## 关键点解析 |
| 137 | + |
| 138 | +- 滑动窗口 |
| 139 | +- 识别题目干扰信息 |
| 140 | +- 看题目限制条件,对于本题有用的信息是`1 <= maxLetters <= 26` |
| 141 | + |
| 142 | +## 扩展 |
| 143 | + |
| 144 | +我们也可以使用滑动窗口来解决,感兴趣的可以试试看。 |
0 commit comments