Leetcode 472. 连接词
题目
给定一个不含重复单词的列表,编写一个程序,返回给定单词列表中所有的连接词。
连接词的定义为:一个字符串完全是由至少两个给定数组中的单词组成的。
示例:
输入: ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]
输出: ["catsdogcats","dogcatsdog","ratcatdogcat"]
解释: "catsdogcats"由"cats", "dog" 和 "cats"组成;
"dogcatsdog"由"dog", "cats"和"dog"组成;
"ratcatdogcat"由"rat", "cat", "dog"和"cat"组成。
说明:
- 给定数组的元素总数不超过 10000。
- 给定数组中元素的长度总和不超过 600000。
- 所有输入字符串只包含小写字母。
- 不需要考虑答案输出的顺序。
题解
字典树+dfs深搜
我们想根据单词列表中的单词建立字典树
然后对每个单词进行依次深搜操作。再选择一个字母时,可能有两种可能,一个是它为一个单词的结尾,也就是说前面的字符串可以构成列表中的单词;一种是它不作为单词的尾部,只作为一个单词的中间部分。这两种情况都需要考虑到
详细过程见代码
代码
struct Trim{
bool flag;
Trim* next[26];
Trim(){
flag = 0;
for(int i=0; i<26; i++)
next[i] = NULL;
}
};
Trim* root = new Trim();
void createTrim(string word){
int len = word.length();
Trim* now = root;
for(int i=0; i<len; i++){
if(now->next[word[i]-'a'] == NULL){
Trim* newT = new Trim();
now->next[word[i]-'a'] = newT;
}
now = now->next[word[i]-'a'];
}
now->flag = 1;
}
vector<string> ans;
bool dfs(int i,int flag,Trim* now,string &nowS){
if(i < nowS.length()){
if(now->next[nowS[i]-'a'] != NULL){
if(now->next[nowS[i]-'a']->flag){ //当前字母可以作为一个单词的结尾
if(dfs(i+1,1,root,nowS)) return true;
}
if(dfs(i+1,flag,now->next[nowS[i]-'a'],nowS)) return true;
}
}else if(flag && now->flag){ //说明这个字符串的前一部分为一个的单词,后一部分也是一个单词,即至少含有两个给定的单词
ans.push_back(nowS);
return true;
}
return false;
}
vector<string> findAllConcatenatedWordsInADict(vector<string>& words) {
int n = words.size();
for(int i=0; i<n; i++){ //建立字典树
if(words[i]=="") continue;
createTrim(words[i]);
}
for(int i=0; i<n; i++){ //对每个单词进行dfs
dfs(0,0,root,words[i]);
}
return ans;
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/concatenated-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。