leetcode

Substring with Concatenation of All Words

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).

The idea is similar to longest substring without repeat chars, use a map to track used words, if the all used word are removed from the map, we found an answer.

 public List<Integer> findSubstring(String S, String[] L) {
        List<Integer> results = new ArrayList<Integer>();
        if (S==null||L==null||L.length==0) {
            return results;
        }

        int wordLength = L[0].length();
        int length = L.length;

        if (S.length()<length*wordLength) {
            return results;
        }

        Map<String, Integer> wordCount = new HashMap<String, Integer>();
        Map<String, Integer> wordFind = new HashMap<String, Integer>();

        for (String str : L) {
            if (wordCount.get(str)==null) {
                wordCount.put(str, 1);
            } else {
                wordCount.put(str, wordCount.get(str)+1);
            }
        }

        int index=0;

        // need <= because "aaa" "a" and "a" 1 <= (3-2) we need to calculate on index=1 too
        while (index<=S.length()-wordLength*length) {
            wordFind.clear();
            wordFind.putAll(wordCount);
            String subStr = S.substring(index, index+wordLength*length);
            while(!subStr.isEmpty()) {
                String word = subStr.substring(0, wordLength);
                if (wordFind.containsKey(word)) {
                    wordFind.put(word, wordFind.get(word)-1);
                    if (wordFind.get(word)==0) {
                        wordFind.remove(word);
                    }
                //no consecutive match, break the inner loop;    
                } else {
                    break;
                }
                subStr = subStr.substring(wordLength, subStr.length());
            }
            if (wordFind.isEmpty()) {
                results.add(index);
            }
            index++;
        }
        return results;

    }