Problem: 30. 串联所有单词的子串
参考题解
滑动窗口
class Solution {public List<Integer> findSubstring(String s, String[] words) {int n = s.length(), m = words.length, w = words[0].length();// 统计 words 中「每个目标单词」的出现次数Map<String, Integer> map = new HashMap<>();for (String str : words)map.put(str, map.getOrDefault(str, 0) + 1);List<Integer> ans = new ArrayList<>();for (int i = 0; i < w; i++) {// 构建一个当前子串对应的哈希表,统计当前子串中「每个目标单词」的出现次数Map<String, Integer> temp = new HashMap<>();// 滑动窗口的大小固定是 m * w,每次将下一个单词添加进 temp,上一个单词移出 tempfor (int j = i; j + w <= n; j += w) {String cur = s.substring(j, j + w);temp.put(cur, temp.getOrDefault(cur, 0) + 1);if (j >= i + (m * w)) { // 说明当前窗口超过了 m 个单词int idx = j - m * w;String prev = s.substring(idx, idx + w);// 移除最左边的单词if (temp.get(prev) == 1)temp.remove(prev);elsetemp.put(prev, temp.get(prev) - 1);// if (!temp.getOrDefault(prev, 0).equals(map.getOrDefault(prev, 0)))// continue;}// if (!temp.getOrDefault(cur, 0).equals(map.getOrDefault(cur, 0)))// continue;// 上面两个 continue 可以减少 map 之间的 equals 操作if (temp.equals(map))ans.add(j - (m - 1) * w);}}return ans;}
}