问题描述:
You are given a string, S, and a list ofwords, L, that are all of the same length. Find all startingindices of substring(s) in S that is a concatenation of each word in L exactlyonce and without any intervening characters.
For example, given:
S: "barfoothefoobarman"
L: ["foo", "bar"]
You should return the indices: [0,9]
.
(order does not matter).
问题分析:
给定一个字符串S和一个字符串数组L,L中的字符串长度都相等,找出S中所有的子串恰好包含L中所有字符各一次,返回子串的起始位置。
采用窗口法;
将所有待级联的字符串数组L添加到一个HashMap中;
代码:
public class Solution {
public List<Integer> findSubstring(String S, String[] L) {
List<Integer> result = new ArrayList<Integer>();
if (L.length == 0 || S.length() < L.length * L[0].length())
return result;
int allNum = L.length, lLength = L[0].length();
HashMap<String, Integer> allMap = new HashMap<String, Integer>(), curMap = new HashMap<>();
// 将L中所有子字符串添加到allMap中
for (String s : L)
allMap.put(s, allMap.containsKey(s) ? allMap.get(s) + 1 : 1);
// 窗口法进行匹配
for (int start = 0; start < lLength; start++) {
curMap.clear();
int count = 0; // 用以统计已经级联的单词个数
for (int left = start, right = start; right + lLength < S.length(); right += lLength) {
String str = S.substring(right, right + lLength);
if (allMap.containsKey(str)) {
curMap.put(str, curMap.containsKey(str) ? curMap.get(str) + 1 : 1);
if (curMap.get(str) <= allMap.get(str))
count++;
while (curMap.get(str) > allMap.get(str)) {
String temp = S.substring(left, left + lLength);
curMap.put(temp, curMap.get(temp) - 1);
if (curMap.get(temp) < allMap.get(temp))
count--;
left += lLength;
}
if (count == allNum) {
result.add(left);
String temp = S.substring(left, left + lLength);
curMap.put(temp, curMap.get(temp) - 1);
count --;
left += lLength;
}
} else { // 如果L中没有的单词,则直接跳过该段,窗口移动到下一段
curMap.clear();
left = right + lLength;
count = 0;
}
}
}
return result;
}
}