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: []
题意:
给定一个无重复单词的字典D,和一个长字符串S。找出S中的子串,该子串恰好是D中所有单词连接而成。
code
1 /* 2 Time: O(n * m ). outter for loop to scan n items, inner for loop to scan m substrings 3 Space: O(m) 4 */ 5 class Solution { 6 public List<Integer> findSubstring(String s, String[] words) { 7 List<Integer> result = new ArrayList<>(); 8 // corner case 9 if (words.length == 0 || s.length() == 0) return result; 10 11 int wordLength = words[0].length(); 12 int catLength = wordLength * words.length; // 求Concatenation长度。 因为题干说words中每个单词长度一致。 13 // corner case 14 if (s.length() < catLength) return result; 15 16 Map<String, Integer> map = new HashMap<>(); 17 for (String word : words) 18 map.put(word, map.getOrDefault(word, 0) + 1); // words中有单词可能出现多次 19 20 // 终结到s.length() - catLength因为最后一部分catLength长度的串可能是一个valid Concatenation解 21 for (int i = 0; i <= s.length() - catLength; ++i) { 22 // deep copy 23 Map<String, Integer> checkingMap = new HashMap<>(map); 24 25 for (int j = i; j < i + catLength; j = j + wordLength) { 26 final String key = s.substring(j, j + wordLength); 27 final int freq = checkingMap.getOrDefault(key, -1); 28 29 if (freq == -1 || freq == 0) break; 30 31 checkingMap.put(key, freq - 1); 32 if (freq - 1 == 0) checkingMap.remove(key); 33 } 34 35 if (checkingMap.size() == 0) result.add(i); 36 } 37 return result; 38 } 39 }