C# DP solution
\npublic class Solution {\n    public IList<string> FindAllConcatenatedWordsInADict(string[] words) {\n        \n        List<string> res = new List<string>();\
```\npublic class Solution {\n    public IList<string> FindAllConcatenatedWordsInADict(string[] words) {\n        \n        List<string> res = new List<string>();\n        if(words == null || words.Length == 0)\n            return res;\n      \n        HashSet<string> wordSet = new HashSet<string>();\n        Array.Sort(words, (a,b) => a.Length - b.Length);\n        foreach(var word in words)\n        {\n            if(IsConcatenated(word, wordSet))\n                res.Add(word);\n            \n            wordSet.Add(word);\n        }\n        \n        return res;\n    }\n    \n    public bool IsConcatenated(string word, HashSet<string> wordSet)\n    {\n        if(wordSet.Count == 0)\n            return false;\n        \n        bool[] dp = new bool[word.Length + 1];\n        dp[0] = true;\n        \n        // check substrings starting with length 1 for current word\n        for(int i = 1; i <= word.Length; i++)\n        {\n            // check if the substring is concatenated\n            // divide the substring into 2 parts, the 1st part has length j\n            for(int j = 0; j < i; j++)\n            {                \n                if(dp[j] && wordSet.Contains(word.Substring(j, i - j)))\n                {\n                    dp[i] = true;\n                    break;\n                }\n            }\n        }\n        \n        return dp[word.Length];\n    }\n}\n```
[]