472. Concatenated Words

Difficulty:
Related Topics:
Similar Questions:

Problem

Given an array of strings words (without duplicates), return **all the *concatenated words* in the given list of** words.

A concatenated word is defined as a string that is comprised entirely of at least two shorter words in the given array.

  Example 1:

Input: words = ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]
Output: ["catsdogcats","dogcatsdog","ratcatdogcat"]
Explanation: "catsdogcats" can be concatenated by "cats", "dog" and "cats"; 
"dogcatsdog" can be concatenated by "dog", "cats" and "dog"; 
"ratcatdogcat" can be concatenated by "rat", "cat", "dog" and "cat".

Example 2:

Input: words = ["cat","dog","catdog"]
Output: ["catdog"]

  Constraints:

Solution (Java)

class Solution {     
    public List<String> findAllConcatenatedWordsInADict(String[] words) {

        //sort the array in asc order of word length, since longer words are formed by shorter words.
        Arrays.sort(words, (a,b) -> a.length() - b.length());

        List<String> result = new ArrayList<>();

        //list of shorter words 
        HashSet<String> preWords = new HashSet<>();

        for(int i=0; i< words.length; i++){
            //Word Break-I problem.
            if(wordBreak(words[i], preWords)) result.add(words[i]);
            preWords.add(words[i]);
        }
        return result;
    }

    private boolean wordBreak(String s, HashSet<String> preWords){
        if(preWords.isEmpty()) return false;

        boolean[] dp = new boolean[s.length() + 1];
        dp[0] = true;

        for(int i = 1; i <= s.length(); i++){
            for(int j = 0; j < i; j++){
                if(dp[j] && preWords.contains(s.substring(j, i))){
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[s.length()];
    }
}  

Solution (Javascript)

/**
 * @param {string[]} words
 * @return {string[]}
 */
var findAllConcatenatedWordsInADict = function(words) {
    let m = new Map(), memo = new Map();
    let res = [];
    for (let i = 0; i < words.length; i++) {
        m.set(words[i], 1);
    }
    for (let i = 0; i < words.length; i++) {
        if (isConcat(words[i], m, memo)) res.push(words[i]);
    }
    return res;
};

function isConcat(word, m, memo) {
    if (memo.has(word)) return memo.get(word);
    for (let i = 1; i < word.length; i++) {
        let prefix = word.slice(0, i);
        let suffix = word.slice(i);
        if (m.has(prefix) && (m.has(suffix) || isConcat(suffix, m, memo))) {
            memo.set(word, true);
            return true;
        }
    }

    memo.set(word, false);
    return false;
};

Explain:

nope.

Complexity: