[Recursion, Memoization] JS Solution
\nvar findAllConcatenatedWordsInADict = function(words) {\n    let m = new Map(), memo = new Map();\n    let res = [];\n    for (let i = 0; i < words.length; i+
```\nvar findAllConcatenatedWordsInADict = function(words) {\n    let m = new Map(), memo = new Map();\n    let res = [];\n    for (let i = 0; i < words.length; i++) {\n        m.set(words[i], 1);\n    }\n    for (let i = 0; i < words.length; i++) {\n        if (isConcat(words[i], m, memo)) res.push(words[i]);\n    }\n    return res;\n};\n\nfunction isConcat(word, m, memo) {\n    if (memo.has(word)) return memo.get(word);\n    for (let i = 1; i < word.length; i++) {\n        let prefix = word.slice(0, i);\n        let suffix = word.slice(i);\n        if (m.has(prefix) && (m.has(suffix) || isConcat(suffix, m, memo))) {\n            memo.set(word, true);\n            return true;\n        }\n    }\n    \n    memo.set(word, false);\n    return false;\n};\n\n// Time Complexity: O(n*k^2) where k is the maximum length of word\n// Space Complexity: O(max(n, k)) because call stack can go as much as k\n```
['JavaScript']