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:
L:
S:
"barfoothefoobarman"
L:
["foo", "bar"]
You should return the indices:
(order does not matter).
Solution:[0,9]
.(order does not matter).
First we process the list of words into a hashtable that points each word to the possitions in the list of words. This is done in O(n). Then we create a window of size $L\cdot \text{wordSize}$ that we make it advance each time by wordSize, this way each time a candidate word leaves the window and a candidate word enters it. Each word can be removed or added in O($\text{wordSize}$). This makes the total running time O($L+ \text{wordSize} n$) = O(L+n).
public class Solution {
public ArrayList<Integer> findSubstring(String S, String[] L)
{
if (L.length==0 || S.length()==0)
return null;
ArrayList<Integer> solution = new ArrayList<Integer>();
//Preprocess the words into the map
HashMap<String,ArrayList<Integer>> map = new HashMap<String,ArrayList<Integer>>();
for(int i=0; i<L.length; i++)
{
if(map.containsKey(L[i]))
{
ArrayList<Integer> temp = map.get(L[i]);
temp.add(i);
}
else
{
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(i);
map.put(L[i], temp);
}
}
int size = L[0].length();
//the windows advance by size, so have to repeat it size times to obtain all the possible windows
for(int i=0; i<size; i++)
{
int found[]=new int[L.length];
int wordsFound=0;
for(int j=0; j<(S.length()-i)/size; j++)
{
//Remove the word that goes out of the window
if(j>=L.length)
{
String temp = S.substring((j-L.length)*size+i,i+(j-L.length)*size+size);
if(map.containsKey(temp))
{
if(found[map.get(temp).get(0)]--<=map.get(temp).size())
wordsFound--;
}
}
//Adding the new word to the window
String temp = S.substring(j*size+i,i+j*size+size);
if(map.containsKey(temp))
{
if(found[map.get(temp).get(0)]++ < map.get(temp).size())
wordsFound++;
}
//Check if the window has all the words
if(wordsFound==L.length)
solution.add((j-L.length+1)*size+i);
}
}
return solution;
}
}
No comments :
Post a Comment