问题描述:
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; } }