classSolution: deffindSubstring(self, s: str, words: List[str]) -> List[int]: result = [] ifnot s ornot words: return result word_len = len(words[0]) total_len = len(words) * word_len word_count = Counter(words) for i inrange(word_len): left, right = i, i current_count = Counter() while right + word_len <= len(s): current_word = s[right:right + word_len] right += word_len current_count[current_word] += 1 while current_count[current_word] > word_count[current_word]: left_word = s[left:left + word_len] left += word_len current_count[left_word] -= 1 if right - left == total_len: result.append(left) return result
classSolution { funcfindSubstring(_s: String, _words: [String]) -> [Int] { guard!s.isEmpty, !words.isEmpty, !words[0].isEmpty else { return [] } let wordLength = words[0].count let wordCount = words.count let totalLength = wordLength * wordCount let sArray =Array(s) var results: [Int] = [] var wordsDict: [String: Int] = [:] for word in words { wordsDict[word, default: 0] +=1 } for i in0..<wordLength { var left = i var right = i var currentDict: [String: Int] = [:] var valid =0 while right + wordLength <= s.count { let currentWord =String(sArray[right..<right + wordLength]) right += wordLength iflet count = currentDict[currentWord] { currentDict[currentWord] = count +1 if count +1== wordsDict[currentWord] { valid +=1 } } while right - left >= totalLength { if valid == wordsDict.count { results.append(left) } let leftWord =String(sArray[left..<left + wordLength]) left += wordLength iflet count = currentDict[leftWord] { if count == wordsDict[leftWord] { valid -=1 } currentDict[leftWord] = count -1 } } } } return results } }
classSolution { funfindSubstring(s: String, words: Array<String>): List<Int> { val result = mutableListOf<Int>() if (s.isEmpty() || words.isEmpty() || s.length < words[0].length || s.length < words[0].length * words.size) { return result } val wn = words[0].length val count = words.groupBy { it }.mapValues { it.value.size } val wordFreq = IntArray(count.size) val uniqWords = count.keys.toList() uniqWords.forEachIndexed { index, w -> wordFreq[index] = count[w]!! } val matchIndex = IntArray(s.length) { -1 } ACTree(uniqWords).match(s) { pos, strIndex, _ -> matchIndex[pos] = strIndex } val freq = wordFreq.clone() for (i in0 until wn) { var j = i while (j < matchIndex.size && matchIndex[j] == -1) j += wn var dist = words.size var left = j var right = j wordFreq.copyInto(freq) while (right < matchIndex.size) { if (matchIndex[right] == -1) { right += wn left = right dist = words.size wordFreq.copyInto(freq) continue } if (--freq[matchIndex[right]] >= 0) dist-- right += wn while (dist == 0) { if (right - left == words.size * wn) { result.add(left) } if (++freq[matchIndex[left]] > 0) dist++ left += wn } } } return result } classACTree(val strs: List<String>) { val root = AcNode('a') init { strs.forEachIndexed { i, it -> putString(i, it) } buildFailurePointer() } classAcNode(vardata: Char) { val children = arrayOfNulls<AcNode>(26) var isEndingChar = false var length = 0 var fail: AcNode? = null var strIndex = 0 } privatefunputString(index: Int, str: String) { var p = root str.forEach { val next = p.children[it - 'a'] if (next != null) { p = next } else { val new = AcNode(it) new.length = p.length + 1 p.children[it - 'a'] = new p = new } } p.isEndingChar = true p.strIndex = index } privatefunbuildFailurePointer() { val queue: Queue<AcNode> = LinkedList() root.fail = null queue.add(root) while (queue.isNotEmpty()) { val p: AcNode = queue.remove() for (i in0..25) { val pc = p.children[i] ?: continue if (p == root) { pc.fail = root } else { var q = p.fail while (q != null) { val qc = q.children[pc.data - 'a'] if (qc != null) { pc.fail = qc break } q = q.fail } if (q == null) { pc.fail = root } } queue.add(pc) } } } funmatch(text: String, action: (pos: Int, strIndex: Int, str: String) -> Unit) { val n = text.length var p: AcNode? = root for (i in0 until n) { val idx = text[i] - 'a' while (p!!.children[idx] == null && p != root) { p = p.fail } p = p.children[idx] if (p == null) p = root var tmp = p while (tmp != root) { if (tmp!!.isEndingChar) { val pos = i - tmp.length + 1 action(pos, tmp.strIndex, strs[tmp.strIndex]) } tmp = tmp.fail } } } } }
classSolution{ List<int> findSubstring(String s, List<String> words) { var wordMap = <String, int>{}; for (String word in words) { wordMap.putIfAbsent(word, () => wordMap.length); } var wordCounts = List<int>.filled(wordMap.length, 0); for (String word in words) { wordCounts[wordMap[word]!]++; } var result = <int>[]; int sLen = s.length; int wordNum = words.length; int wordLen = words[0].length; int len = wordLen * wordNum; for (int i = 0; i < wordLen; i++) { for (int j = i; j <= sLen - len; j += wordLen) { var windowCounts = List<int>.filled(wordMap.length, 0); for (int k = wordNum - 1; k >= 0; k--) { int begin = j + k * wordLen; String word = s.substring(begin, begin + wordLen); int index = wordMap[word] ?? -1; if (index == -1 || windowCounts[index]++ == wordCounts[index]) { j = begin; break; } if (k == 0) { result.add(j); } } } } return result; } }
# @param {String} s # @param {String[]} words # @return {Integer[]} deffind_substring(s, words) result = [] word_map = Hash.new(0) return result if words.empty? || words[0].empty? || s.length < words.length * words[0].length word_len, word_num = words[0].length, words.length total_len = word_len * word_num words.each { |word| word_map[word] += 1 } (0...word_len).each do |i| left = i right = i window = Hash.new(0) while right + word_len <= s.length current_word = s[right, word_len] right += word_len window[current_word] += 1 while window[current_word] > word_map[current_word] left_word = s[left, word_len] left += word_len window[left_word] -= 1 end result << left if right - left == total_len end end result end
objectSolution{ deffindSubstring(s: String, words: Array[String]): List[Int] = { var result = ListBuffer[Int]() if (s.isEmpty || words.isEmpty || s.length < words(0).length * words.length) { return result.toList } val wordLen = words(0).length val wordNum = words.length val totalLen = wordLen * wordNum val wordMap = words.groupBy(identity).mapValues(_.length) for (i <- 0 until wordLen) { var left = i var right = i var window = scala.collection.mutable.Map[String, Int]().withDefaultValue(0) while (right + wordLen <= s.length) { val currentWord = s.substring(right, right + wordLen) right += wordLen window(currentWord) += 1 while (window(currentWord) > wordMap.getOrElse(currentWord, 0)) { val leftWord = s.substring(left, left + wordLen) left += wordLen window(leftWord) -= 1 } if (right - left == totalLen) { result += left } } } result.toList } }