题目
You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.
For example, given:
S: "barfoothefoobarman"
L: ["foo", "bar"]
You should return the indices: [0,9]
.
(order does not matter).
这道题和Minimum Window Substring思路一致,也是双指针遍历。
需要注意的时,移动指针时,按单词长度移动。
代码
import java.util.ArrayList;
import java.util.HashMap;
public class SubstringWithConcatenationOfAllWords {
public ArrayList<Integer> findSubstring(String S, String[] L) {
ArrayList<Integer> results = new ArrayList<Integer>();
if (S == null || S.length() == 0 || L == null || L.length == 0) {
return results;
}
int N = S.length();
int M = L.length;
int T = L[0].length();
HashMap<String, Integer> needToFind = new HashMap<String, Integer>();
HashMap<String, Integer> hasFound = new HashMap<String, Integer>();
for (int i = 0; i < M; ++i) {
int count = 1;
if (needToFind.containsKey(L[i])) {
count += needToFind.get(L[i]);
}
needToFind.put(L[i], count);
}
for (int j = 0; j < T; ++j) {
int hits = 0;
int start = j;
for (int i = j; i + T <= N; i += T) {
String word = S.substring(i, i + T);
if (!needToFind.containsKey(word)) {
hasFound.clear();
hits = 0;
start = i + T;
continue;
}
int count = 1;
if (hasFound.containsKey(word)) {
count += hasFound.get(word);
}
if (count <= needToFind.get(word)) {
++hits;
hasFound.put(word, count);
} else {
String startWord = S.substring(start, start + T);
while (!startWord.equals(word)) {
int value = hasFound.get(startWord) - 1;
hasFound.put(startWord, value);
--hits;
start += T;
startWord = S.substring(start, start + T);
}
start += T;
}
if (hits == M) {
results.add(start);
String startWord = S.substring(start, start + T);
int value = hasFound.get(startWord) - 1;
hasFound.put(startWord, value);
--hits;
start += T;
}
}
hasFound.clear();
}
return results;
}
}