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 }