0030. Substring With Concatenation of All Words

30. Substring with Concatenation of All Words #

Problem #

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

Example 1:


Input:
  s = "barfoothefoobarman",
  words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.

Example 2:


Input:
  s = "wordgoodgoodgoodbestword",
  words = ["word","good","best","word"]
Output: []

Problem Summary #

Given a source string s and an array of strings, find the starting indices in the source string of continuous strings formed by various combinations of the string array. If there are multiple, all of them need to be output in the result.

Solution Approach #

This problem seems difficult, but there are 2 constraints that make it not particularly hard. 1. The strings in the string array are all of the same length. 2. The strings in the string array are required to be concatenated continuously, and their order can be any permutation.

The solution approach is to first store all strings in the string array in a map and accumulate their occurrence counts. Then scan the source string from the beginning. Each time, determine whether all strings in the string array have been used up (whether the counts are 0). If they have all been used up, and the length is exactly the total length of any permutation of the string array, record the starting index of this combination. If it does not match, continue examining the next character of the source string until the entire source string has been scanned.

Code #


package leetcode

func findSubstring(s string, words []string) []int {
	if len(words) == 0 {
		return []int{}
	}
	res := []int{}
	counter := map[string]int{}
	for _, w := range words {
		counter[w]++
	}
	length, totalLen, tmpCounter := len(words[0]), len(words[0])*len(words), copyMap(counter)
	for i, start := 0, 0; i < len(s)-length+1 && start < len(s)-length+1; i++ {
		//fmt.Printf("sub = %v i = %v lenght = %v start = %v tmpCounter = %v totalLen = %v\n", s[i:i+length], i, length, start, tmpCounter, totalLen)
		if tmpCounter[s[i:i+length]] > 0 {
			tmpCounter[s[i:i+length]]--
			//fmt.Printf("******sub = %v i = %v lenght = %v start = %v tmpCounter = %v totalLen = %v\n", s[i:i+length], i, length, start, tmpCounter, totalLen)
			if checkWords(tmpCounter) && (i+length-start == totalLen) {
				res = append(res, start)
				continue
			}
			i = i + length - 1
		} else {
			start++
			i = start - 1
			tmpCounter = copyMap(counter)
		}
	}
	return res
}

func checkWords(s map[string]int) bool {
	flag := true
	for _, v := range s {
		if v > 0 {
			flag = false
			break
		}
	}
	return flag
}

func copyMap(s map[string]int) map[string]int {
	c := map[string]int{}
	for k, v := range s {
		c[k] = v
	}
	return c
}



Calendar Jun 25, 2026
Edit Edit this page
Total visits:   You are visitor No.
中文