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).
Java:
http://blog.csdn.net/linhuanmars/article/details/20342851
public class Solution {
public ArrayList<Integer> findSubstring(String S, String[] L) {
ArrayList<Integer> res = new ArrayList<Integer>();
if(S==null||S.length()==0||L==null||L.length==0) return res;//all parameter can not be null
HashMap<String,Integer> map= new HashMap<String,Integer>();
// build dic using L
for(int i=0;i<L.length;i++)
{
if(map.containsKey(L[i]))
{
map.put(L[i],map.get(L[i])+1);
}
else{
map.put(L[i],1);
}
}
//
for(int i=0;i<L[0].length();i++)//<span style="color: rgb(34, 34, 34); font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px; line-height: 18.4799995422363px;">做法是i从0到l-1个字符开始,得到开始index分别为i, i+l, i+2*l, ...的长度为l的单词。这样就可以保证判断到所有的满足条件的串</span>
{
HashMap<String,Integer> curMap= new HashMap<String,Integer>();
int count=0;
int left=i;
for(int j=i;j<=S.length()-L[0].length();j+=L[0].length())
{
String str= S.substring(j,j+L[0].length());
if(map.containsKey(str))
{
if(curMap.containsKey(str))
{
curMap.put(str,curMap.get(str)+1);
}
else{
curMap.put(str,1);
}
if(curMap.get(str)<=map.get(str))
{
count++;
}
else
{
while(curMap.get(str)>map.get(str))//if str is repeat, <span style="font-family: Arial, Helvetica, sans-serif;">we has to move from left to current j, </span><span style="font-family: Arial, Helvetica, sans-serif;">loop to remove every addded word, until find and remove the repeated string, and set up a new left,</span>
{
String temp=S.substring(left,left+L[0].length());
if(curMap.containsKey(temp))
{
curMap.put(temp,curMap.get(temp)-1);
if(curMap.get(temp)<map.get(temp))
count--; //until str number is in the range, count--
}
left+=L[0].length();
}
}
if(count==L.length)
{
res.add(left);
//if(left<)
String temp = S.substring(left,left+L[0].length());
if(curMap.containsKey(temp))
{
curMap.put(temp,curMap.get(temp)-1);
}
count--;
left+=L[0].length();
}
}
else{
curMap.clear();
count=0;
left=j+L[0].length();
}
}
}
return res;
}
}
Q:为什么外层循环只需单词长度次就够了
A:其实这里就是从一个元素出发,然后我们会对固定长度的单词依次扫过去,既然这样,那么只需要扫单位长度次就够了,举个例子可能比较好理解,比如abcdefghijklmn, 长度是3, 那么从a出发,我们会扫abc, def,ghi,jkl, 接下来从b出发,是bcd,efg,hij,klm,然后是从c出发,是cde, fgh, ijk, lmn. 如果接下来继续,从d出发,是def,ghi,jkl,可以发现扫a的时候已经判断过这些单词了~ 所以就不需要再跑一次了哈~