Daily Archives: July 19, 2016

Word Break II

leetcode 140.

Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.

Return all such possible sentences.

For example, given
s = "catsanddog",
dict = ["cat", "cats", "and", "sand", "dog"].

A solution is ["cats and dog", "cat sand dog"].

Solution. Below code is my classical permutation solution:

public static List<String> wordBreak2(String s, Set<String> wordDict) {
    List<String> ans = new ArrayList<>();
    helper2(s, wordDict, "", ans, 0);
    return ans;
}

// this is the tradition, classical permutation. But it won't memorize the part result.
public static void helper2(String s, Set<String> wordDict, String curr, List<String> ans, int pos) {
    if (pos == s.length()) {
        ans.add(curr.substring(1, curr.length()));
        return;
    }
    for (String word : wordDict) {
        if (pos + word.length() <= s.length() && s.substring(pos, pos + word.length()).equals(word)) {
            helper2(s, wordDict, curr + " " + word, ans, pos + word.length());
        }
    }
}

But it didn’t pass the hot-discussed [a, aa, aaa, …, ], “aaa…aba…aaaaa” test case. The reason is because the traditional permutation doesn’t memorize the history. It just simply permutates all possibilities. Up to now, I haven’t been able to figure out how to use the classical permutation solution to memorize the middle result.

A better solution is that helper function returns a list. The returning list will permutate with current word:

wordbreakii

This is another classical permutation solution too. The difference is that this solution takes up more space to memorize each String’s answer.

public static List<String> wordBreak(String s, Set<String> wordDict) {
    return helper(s, wordDict, new HashMap<>());
}

// the helper returns a result list. Put this list into hashmap. This can help to memorize the result.
public static List<String> helper(String s, Set<String> wordDict, Map<String, List<String>> mem) {
    if (mem.containsKey(s)) {
        return mem.get(s);
    }
    List<String> ans = new ArrayList<>();
    if (s.length() == 0) {
        ans.add("");
        return ans;
    }
    for (String word : wordDict) {
        if (s.startsWith(word)) {
            List<String> currList = helper(s.substring(word.length()), wordDict, mem);
            for (String subList : currList) {
                ans.add(word + (subList.isEmpty() ? "" : " ") + subList);
            }
        }
    }
    mem.put(s, ans);
    return ans;
}

Check my code on github.