原题网址:https://leetcode.com/problems/substring-with-concatenation-of-all-words/
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 wordsexactly once and without any intervening characters.
For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]
You should return the indices: [0,9]
.
(order does not matter).
方法:使用直方图统计。
public class Solution {
public List<Integer> findSubstring(String s, String[] words) {
Map<String, Integer> histograms = new HashMap<>();
for(String word: words) {
Integer count = histograms.get(word);
if (count == null) {
count = 1;
} else {
count ++;
}
histograms.put(word, count);
}
Map<String, Integer> wordCounts = new HashMap<>();
List<Integer> substrings = new ArrayList<>();
int m = words[0].length();
int n = s.length();
for(int offset = 0; offset < m; offset ++) {
int matched = 0;
int pos = offset;
wordCounts.clear();
for(int i=offset; i+m<=n; i+=m) {
String word = s.substring(i, i+m);
if (!histograms.containsKey(word)) {
wordCounts.clear();
matched = 0;
pos = i+m;
continue;
}
Integer count = wordCounts.get(word);
if (count == null || count < histograms.get(word)) {
matched ++;
}
if (count == null) {
count = 1;
} else {
count ++;
}
wordCounts.put(word, count);
if (matched == words.length) {
substrings.add(pos);
}
if (pos + (words.length-1)*m <= i) {
String prev = s.substring(pos, pos+m);
// System.out.printf("removing %s\n", prev);
Integer pc = wordCounts.get(prev);
if (pc <= histograms.get(prev)) matched --;
pc --;
wordCounts.put(prev, pc);
pos += m;
}
}
}
return substrings;
}
}
另一种实现:
public class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> results = new ArrayList<>();
if (s == null || words == null || words.length == 0) return results;
Map<String, Integer> h = new HashMap<>();
for(String word : words) {
Integer c = h.get(word);
if (c == null) c = 1; else c++;
h.put(word, c);
}
int len = words[0].length();
for(int offset = 0; offset < len; offset++) {
Map<String, Integer> f = new HashMap<>();
int from = offset;
int count = 0;
for(int i = offset; i + len <= s.length(); i += len) {
String word = s.substring(i, i + len);
Integer hc = h.get(word);
if (hc == null) {
from = i + len;
count = 0;
f = new HashMap<>();
continue;
}
Integer fc = f.get(word);
if (fc == null) fc = 1; else fc++;
f.put(word, fc);
count++;
while (fc > hc) {
String fword = s.substring(from, from + len);
f.put(fword, f.get(fword) - 1);
fc = f.get(word);
from += len;
count--;
}
if (count == words.length) {
results.add(from);
}
}
}
return results;
}
}