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.