|
1 | 1 | package g0001_0100.s0030_substring_with_concatenation_of_all_words
|
2 | 2 |
|
3 | 3 | // #Hard #String #Hash_Table #Sliding_Window #Top_Interview_150_Sliding_Window
|
4 |
| -// #2023_07_03_Time_182_ms_(100.00%)_Space_37.9_MB_(100.00%) |
| 4 | +// #2025_03_04_Time_14_ms_(98.62%)_Space_39.70_MB_(91.72%) |
5 | 5 |
|
6 | 6 | class Solution {
|
7 | 7 | fun findSubstring(s: String, words: Array<String>): List<Int> {
|
8 |
| - val indices: MutableList<Int> = ArrayList() |
9 |
| - if (words.size == 0) { |
10 |
| - return indices |
| 8 | + val ans: MutableList<Int> = ArrayList<Int>() |
| 9 | + val n1 = words[0].length |
| 10 | + val n2 = s.length |
| 11 | + val map1: MutableMap<String, Int> = HashMap<String, Int>() |
| 12 | + for (ch in words) { |
| 13 | + map1.put(ch, map1.getOrDefault(ch, 0) + 1) |
11 | 14 | }
|
12 |
| - // Put each word into a HashMap and calculate word frequency |
13 |
| - val wordMap: MutableMap<String, Int> = HashMap() |
14 |
| - for (word in words) { |
15 |
| - wordMap[word] = wordMap.getOrDefault(word, 0) + 1 |
16 |
| - } |
17 |
| - val wordLength = words[0].length |
18 |
| - val window = words.size * wordLength |
19 |
| - for (i in 0 until wordLength) { |
20 |
| - // move a word's length each time |
| 15 | + for (i in 0..<n1) { |
| 16 | + var left = i |
21 | 17 | var j = i
|
22 |
| - while (j + window <= s.length) { |
23 |
| - // get the subStr |
24 |
| - val subStr = s.substring(j, j + window) |
25 |
| - val map: MutableMap<String, Int> = HashMap() |
26 |
| - // start from the last word |
27 |
| - for (k in words.indices.reversed()) { |
28 |
| - // get the word from subStr |
29 |
| - val word = subStr.substring(k * wordLength, (k + 1) * wordLength) |
30 |
| - val count = map.getOrDefault(word, 0) + 1 |
31 |
| - // if the num of the word is greater than wordMap's, move (k * wordLength) and |
32 |
| - // break |
33 |
| - if (count > wordMap.getOrDefault(word, 0)) { |
34 |
| - j = j + k * wordLength |
35 |
| - break |
36 |
| - } else if (k == 0) { |
37 |
| - indices.add(j) |
38 |
| - } else { |
39 |
| - map[word] = count |
| 18 | + var c = 0 |
| 19 | + val map2: MutableMap<String, Int> = HashMap<String, Int>() |
| 20 | + while (j + n1 <= n2) { |
| 21 | + val word1 = s.substring(j, j + n1) |
| 22 | + j += n1 |
| 23 | + if (map1.containsKey(word1)) { |
| 24 | + map2.put(word1, map2.getOrDefault(word1, 0) + 1) |
| 25 | + c++ |
| 26 | + while (map2[word1]!! > map1[word1]!!) { |
| 27 | + val word2 = s.substring(left, left + n1) |
| 28 | + map2.put(word2, map2[word2]!! - 1) |
| 29 | + left += n1 |
| 30 | + c-- |
| 31 | + } |
| 32 | + if (c == words.size) { |
| 33 | + ans.add(left) |
40 | 34 | }
|
| 35 | + } else { |
| 36 | + map2.clear() |
| 37 | + c = 0 |
| 38 | + left = j |
41 | 39 | }
|
42 |
| - j = j + wordLength |
43 | 40 | }
|
44 | 41 | }
|
45 |
| - return indices |
| 42 | + return ans |
46 | 43 | }
|
47 | 44 | }
|
0 commit comments