Python | Trie + Memo | Simple
\nclass Solution:\n    def findAllConcatenatedWordsInADict(self, words):\n        t, memo, res = Trie(), {}, []\n        for word in words:\n            t.add(w
```\nclass Solution:\n    def findAllConcatenatedWordsInADict(self, words):\n        t, memo, res = Trie(), {}, []\n        for word in words:\n            t.add(word)\n        for word in words:\n            if t.helper(word, 0, len(word) - 1, 0, memo):\n                res.append(word)\n        return res\n\n\nclass Node:\n    def __init__(self):\n        self.children = {}\n        self.is_end = False\n\n\nclass Trie:\n    def __init__(self):\n        self.root = Node()\n\n    def add(self, word):\n        p = self.root\n        for c in word:\n            if c not in p.children:\n                p.children[c] = Node()\n            p = p.children[c]\n        p.is_end = True\n\n\n    def helper(self, word, st, end, cnt, memo):\n        p = self.root\n        curr = word[st: end + 1]\n        if curr in memo: \n            return memo[curr]\n        \n        for x in range(st, end + 1):\n            if word[x] in p.children:\n                p = p.children[word[x]]\n                if p.is_end:\n                    if x == end:\n                        return cnt >= 1\n                    if self.helper(word, x + 1, end, cnt + 1, memo):\n                        memo[curr] = True\n                        return True\n            else:\n                break\n                \n        memo[curr] = False\n        return False\n```
['Trie', 'Recursion', 'Python']