|  | 
| 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