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 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).
Solution
from collections import defaultdict
class Solution(object):
    def findSubstring(self, s, words):
        """
        :type s: str
        :type words: List[str]
        :rtype: List[int]
        """
        result, n_word, l_word  = [], len(words), len(words[0])
        word_map = defaultdict(int)
        for i in words:
            word_map[i] += 1
        for i in range((len(s) + 1) - n_word * l_word):
            cur, j, = defaultdict(int), 0
            while j < n_word:
                word = s[i + j * l_word: i + j * l_word + l_word]
                if word not in word_map:
                    break
                cur[word] += 1
                if cur[word] > word_map[word]:
                    break
                j += 1
            if j == n_word:
                result.append(i)
        return result
public class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> res = new ArrayList<>();
        if(s == null || words == null || words.length == 0) return res;
        int len = words[0].length();
        Map<String, Integer> map = new HashMap<>();
        for(String word : words)
            map.put(word, map.containsKey(word) ? map.get(word) + 1 : 1);
        for(int i = 0;i <= s.length() - len * words.length;i++) {
            Map<String, Integer> copy = new HashMap<>(map);
            for(int j = 0;j<words.length;j++) {
                String cur = s.substring(i + j * len, i + j* len + len);
                if(copy.containsKey(cur)) {
                    int count = copy.get(cur);
                    if(count == 1) copy.remove(cur);
                    else copy.put(cur, count - 1);
                    if(copy.isEmpty()) {
                        res.add(i);
                        break;
                    }
                } else break;
            }
        }
        return res;
    }
}