Fast Python DP solution
\n\'\'\'\nIf a word can be Concatenated from shorter words, then word[:i] and word[i:] must also be Concatenated from shorter words.\nBuild results of word from
```\n\'\'\'\nIf a word can be Concatenated from shorter words, then word[:i] and word[i:] must also be Concatenated from shorter words.\nBuild results of word from results of word[:i] and word[i:]\nIterate i from range(1, len(word)) to avoid a word is Concatenated from itself.\nUse memorization to avoid repeat calculation.\nTime: O(n*l)\nSpace: O(n)\n\'\'\'\nclass Solution:\n    def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]:\n        mem = {}\n        words_set = set(words)\n        return [w for w in words if self.check(w, words_set, mem)]\n    \n    def check(self, word, word_set, mem):\n        if word in mem:\n            return mem[word]\n        mem[word] = False\n        for i in range(1, len(word)):\n            if word[:i] in word_set and (word[i:] in word_set or self.check(word[i:], word_set, mem)):\n                mem[word] = True\n                break\n        return mem[word]\n```
['Dynamic Programming']