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]
.
(order does not matter).
这个题用brute force是AC的,
优化的方案是sliding window,不过要遍历len(word in words)次
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> rst = new ArrayList<Integer>();
Map<String, Integer> map = new HashMap<String, Integer>();
int len = words[0].length(), n = words.length;
for(String word : words) map.put(word, map.containsKey(word) ? map.get(word) + 1 : 1);
for(int i=0; i<=s.length()-n*len; i++) {
Map<String, Integer> temp = new HashMap<String, Integer>(map);
boolean f = true;
for(int j=0; j<n*len; j+=len) {
String key = s.substring(i+j, i+j+len);
if(!temp.containsKey(key)) { f = false; break; }
int nextVal = temp.get(key)-1;
if(nextVal < 0) { f = false; break; }
temp.put(key, nextVal);
}
if(f) {rst.add(i);}
}
return rst;
}
}
package l30;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/*
* 之前写的暴力解法竟然能过。。。。。
* 用2pointer,可以做到O(len(word in words) * len(s)),
* 从s的0..len(word in words)开始分别走一遍sliding window
*/
class AC {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> ret = new ArrayList<Integer>();
int n = s.length(), m = words[0].length();
for(int i=0; i<m; i++) {
int need = words.length;
// Map还可以优化为不需要每次初始化,在结束当前循环前把p归到q上去
Map<String, Integer> map = new HashMap<String, Integer>();
for(String t : words) map.put(t, map.containsKey(t)?1+map.get(t):1);
// sliding window
int p = i, q = i;
while(true) {
if(need == 0) ret.add(p);
if(q+m > n) break;
String t = s.substring(q, q+m);
if(!map.containsKey(t)) {
// 出现words中没有的,
while(p != q) {
String tt = s.substring(p, p+m);
map.put(tt, map.get(tt) + 1);
p += m;
need ++;
}
q += m;
p = q;
} else if(map.get(t) == 0) {
// 多出个t
while(map.get(t) == 0) {
String tt = s.substring(p, p+m);
map.put(tt, map.get(tt) + 1);
p += m;
need ++;
}
map.put(t, map.get(t) - 1);
need --;
q += m;
} else {
// 正好需要这个string
map.put(t, map.get(t)-1);
need --;
q += m;
}
}
}
return ret;
}
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> ret = new ArrayList<Integer>();
int n = s.length(), m = words[0].length();
Map<String, Integer> map = new HashMap<String, Integer>();
for(String t : words) map.put(t, map.containsKey(t)?1+map.get(t):1);
for(int i=0; i<m; i++) {
int need = words.length;
// sliding window
int p = i, q = i;
while(true) {
if(need == 0) ret.add(p);
if(q+m > n) break;
String t = s.substring(q, q+m);
if(!map.containsKey(t)) {
// 出现words中没有的,
while(p != q) {
String tt = s.substring(p, p+m);
map.put(tt, map.get(tt) + 1);
p += m;
need ++;
}
q += m;
p = q;
} else if(map.get(t) == 0) {
// 多出个t
while(map.get(t) == 0) {
String tt = s.substring(p, p+m);
map.put(tt, map.get(tt) + 1);
p += m;
need ++;
}
map.put(t, map.get(t) - 1);
need --;
q += m;
} else {
// 正好需要这个string
map.put(t, map.get(t)-1);
need --;
q += m;
}
}
while(p != q) {
String tt = s.substring(p, p+m);
map.put(tt, map.get(tt) + 1);
p += m;
}
}
return ret;
}
}