python3 | sort and use trie.
If there is word whose substrings are already in array, the length of each substring would be <= len(word) itself. Here is the logic below. \n1. Sort the array 
If there is word whose substrings are already in array, the length of each substring would be <= len(word) itself. Here is the logic below. \n1. Sort the array based on length of word.\n2. Identify if trie contains already a list of words that make up the word we are looking for using recursion. \n3. If (2) is true, add the word to list ans.\n4. Regardless of (3) add the word to the trie and mark the end of a word by using \'#\'\n\n```\nclass Solution:\n    def check(self, trie, word, widx):\n        if widx == len(word): \n            return True\n        \n        t = trie\n        ret = False\n        \n        for cidx in range(widx, len(word)):\n            if word[cidx] in t:\n                t = t[word[cidx]]\n            else: \n                return False \n            \n            if \'#\' in t: \n                ret |= self.check(trie, word, cidx+1)\n                \n            if ret: \n                return ret\n                \n        return ret\n    \n    def insert(self, word, trie):\n        t = trie\n        for c in word:\n            if c not in t:\n                t[c] = {}\n                \n            t = t[c]\n        t[\'#\'] = {}\n            \n    def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]:\n        words.sort(key=lambda x: len(x))\n        t = {}\n        ans = []\n        for w in words:\n            if self.check(t, w, 0):\n                ans.append(w)\n            self.insert(w, t)\n            \n        return ans\n
['Trie', 'Recursion', 'Python3']