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.
For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]
You should return the indices: [0,9]
.
Difficulty: Hard
Solution:
HashMap<String, Queue<Integer>>
public class Solution {
List<Integer> res = new ArrayList<Integer>();
String[] wordList;
HashMap<String, Queue<Integer>> map = new HashMap<String, Queue<Integer>>();
public List<Integer> findSubstring(String s, String[] words) {
if(words.length == 0) return res;
int len = words[0].length();
for(int i = 0; i < words.length; i++){
if(map.containsKey(words[i])){
map.get(words[i]).offer(-1);
}
else{
Queue<Integer> q = new LinkedList<Integer>();
q.offer(-1);
map.put(words[i], q);
}
}
wordList = new String[s.length() - len + 1];
for(int i = 0; i < wordList.length; i++){
wordList[i] = s.substring(i, i + len);
}
for(int i = 0; i < len; i++){
int begin = 0, index = i, count = 0;
while(begin < s.length()){
// System.out.println(index);
// System.out.println(index - len * count);
// System.out.println("---");
if(words.length == count){
//System.out.println("ADD");
res.add(index - len * count);
count--;
continue;
}
if((words.length - count) * len > s.length() - index){
break;
}
String newWord = wordList[index];
if(!map.containsKey(newWord)){
index += len;
count = 0;
continue;
}
if(map.get(newWord).peek() >= index - count * len && map.get(newWord).peek() < index && (index - map.get(newWord).peek()) % len == 0){
int temp = map.get(newWord).poll();
map.get(newWord).offer(index);
count = (index - temp)/len;
index += len;
continue;
}
else{
map.get(newWord).poll();
map.get(newWord).offer(index);
index += len;
count++;
}
}
if(words.length == count)
res.add(index - len * count);
}
return res;
}
}