Substring with Concatenation of All Words
尋找所有詞連接的子串
思路:由於該字串是所有詞典中的詞連接的,所以該字串長度固定。因此本題可以看作一個滑動窗口的題。為了去除重復工作,每次滑動一個單詞的長度,因此起始位置就有n種(n為單詞長度)。每種起始位置的滑動策略如下:
如果當前窗口滿足條件,則窗口只往后移動一個單詞,並且下一次只檢查最后一個單詞(中間的單詞肯定滿足條件)。
如果當前窗口不滿足條件,則有兩種情況:
1.當前窗口內不滿足條件的第一個單詞不存在於詞典中,則下一個窗口就直接滑到這個單詞的下一個單詞;
2.當前窗口內不滿足條件的第一個單詞存在於詞典中,但是這個單詞已經被前面用完了,則下一個窗口只往后移動一個單詞,並且下一次之間從這個單詞開始檢查。

1 public class Solution { 2 public List<Integer> findSubstring(String s, String[] words) { 3 List<Integer> res = new ArrayList<Integer>(); 4 int m = words.length; 5 int n = words[0].length(); 6 Map<String, Integer> map = new HashMap<String, Integer>(); 7 for (String word : words) { 8 if (map.containsKey(word)) { 9 map.put(word, map.get(word) + 1); 10 } else { 11 map.put(word, 1); 12 } 13 } 14 for (int p = 0; p <= n - 1; p++) { 15 int start = p; 16 while (start + n * m - 1 < s.length()) { 17 int i = 1; 18 boolean moveOneWord = true; 19 Map<String, Integer> copy = new HashMap<String, Integer>(map); 20 while (moveOneWord && start + n * m - 1 < s.length()) { 21 for(; i <= m; i++) { 22 String cut = s.substring(start + (i - 1) * n, start + i * n); 23 if (copy.containsKey(cut)) { 24 if (copy.get(cut) == 0) { 25 moveOneWord = true; 26 break; 27 } else { 28 copy.put(cut, copy.get(cut) - 1); 29 } 30 } else { 31 start += i * n; 32 i = 1; 33 moveOneWord = false; 34 break; 35 } 36 } 37 38 if (i == m + 1) { 39 res.add(start); 40 moveOneWord = true; 41 } 42 if (moveOneWord) { 43 String firstword = s.substring(start, start + n); 44 copy.put(firstword, copy.get(firstword) + 1); 45 start += n; 46 i--; 47 } 48 } 49 } 50 } 51 return res; 52 } 53 }