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.
Subscribe to see which companies asked this question.
给出一个单词的集合,要求找出其中能用集合中的两个(或以上)单词组成的单词。和140题类似,只不过是单词放在了一个集合中。也是用dfs的方法,为了减少重复的计算,比如给出{“a”,"aa","aaa","aaaa"},如果已经计算好了“aa”可以用两个a组成,则用map记录下对应的数值2,。到“aaa”的时候先是遍历到单词的第一部分“a”,对第二部分“aa”用dfs,由于本来就记录好了“aa”对应的数值为2,直接返回2,这时候加起来就是3,只要数值大于1说明了这个单词是有效的答案,而不用管数值是多少了,直接返回数值,这样就能减少很多的运算。
代码:
class Solution {
public:
vector<string> findAllConcatenatedWordsInADict(vector<string>& words)
{
vector<string> res;
if(words.empty()) return res;
for(auto word:words) map[word] = 1;
for(auto word:words)
{
if(dfs(word) > 1) res.push_back(word);
}
return res;
}
private:
unordered_map<string, int> map;
unordered_set<string> set;
int dfs(string& s)
{
int ret = -1;
if(s.empty()) return 0;
if(map.find(s) != map.end() && set.find(s) != set.end()) return map[s];
for(int i = 1; i <= s.size(); ++i)
{
string l = s.substr(0, i), r = s.substr(i);
if(map.find(l) != map.end())
{
int d = dfs(r);
if(d == -1) continue;
ret = max(ret, map[l]+d);
if(ret > 1)
{
map[s] = ret;
set.insert(s);
return ret;
}
}
}
return ret;
}
};