Given a list of words (without duplicates), please write a program that returns all concatenated words in the given list of words.
A concatenated word is defined as a string that is comprised entirely of at least two shorter words in the given array.
Example:
Input: ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"] Output: ["catsdogcats","dogcatsdog","ratcatdogcat"] Explanation: "catsdogcats" can be concatenated by "cats", "dog" and "cats";
"dogcatsdog" can be concatenated by "dog", "cats" and "dog";
"ratcatdogcat" can be concatenated by "rat", "cat", "dog" and "cat".
Note:
- The number of elements of the given array will not exceed
10,000
- The length sum of elements in the given array will not exceed
600,000
. - All the input string will only include lower case letters.
- The returned elements order does not matter.
Approach #1: C++.
class Solution { public: vector<string> findAllConcatenatedWordsInADict(vector<string>& words) { unordered_set<string> dict; vector<string> ans; sort(words.begin(), words.end(), [](string &a, string &b) { return a.length() < b.length(); }); for (string word : words) { if (judge(word, dict)) ans.push_back(word); dict.insert(word); } return ans; } private: bool judge(string &word, unordered_set<string> &dict) { if (word.empty()) { return false; } int len = word.length(); vector<bool> dp(len+1, false); dp[0] = true; for (int i = 1; i <= len; ++i) { for (int j = 0; j < i; ++j) { if (dp[j] && dict.find(word.substr(j, i-j)) != dict.end()) { dp[i] = true; break; } } } return dp[len]; } };
Analysis:
dp[j] : the substring of word.substr(0, j) can be constituted with the word in dict.