在英语中,我们有一个叫做 词根(root) 的概念,可以词根 后面 添加其他一些词组成另一个较长的单词------我们称这个词为 衍生词 (derivative)。例如,词根 help,跟随着 继承词 "ful",可以形成新的单词 "helpful"。
现在,给定一个由许多 词根 组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有 衍生词 用 词根 替换掉。如果 衍生词 有许多可以形成它的 词根,则用 最短 的 词根 替换它。
你需要输出替换之后的句子。
示例 1:
输入:dictionary = ["cat","bat","rat"], sentence = "the cattle was rattled by the battery"
输出:"the cat was rat by the bat"
示例 2:
输入:dictionary = ["a","b","c"], sentence = "aadsfasf absbs bbab cadsfafs"
输出:"a a b c"
提示:
1 <= dictionary.length <= 1000
1 <= dictionary[i].length <= 100
dictionary[i] 仅由小写字母组成。
1 <= sentence.length <= 106
sentence 仅由小写字母和空格组成。
sentence 中单词的总量在范围 [1, 1000] 内。
sentence 中每个单词的长度在范围 [1, 1000] 内。
sentence 中单词之间由一个空格隔开。
sentence 没有前导或尾随空格。
字典树
csharp
class Solution {
private:
struct trie{
vector<trie*> children;
bool isWord;
trie(): children(26, nullptr), isWord(false){};
};
trie* root;
vector<string> split(const string& sentence, char del){
vector<string> result;
string word;
for(char c : sentence){
if(c == del){
if(!word.empty()){
result.push_back(word);
word.clear();
}
}
else{
word += c;
}
}
if(!word.empty()){
result.push_back(word);
}
return result;
}
public:
Solution(){
root = new trie();
}
string replaceWords(vector<string>& dictionary, string sentence) {
for(string word : dictionary){
add(word);
}
vector<string> words = split(sentence, ' ');
vector<string> ans;
for(string word : words){
ans.push_back(findPrefix(word));
}
string res;
for(int i = 0; i < ans.size() - 1; i++){
res += ans[i];
res += ' ';
}
res += ans[ans.size() - 1];
return res;
}
void add(string word){
trie* node = root;
for(char ch : word){
ch -= 'a';
if(node->children[ch] == nullptr){
node->children[ch] = new trie();
}
node = node->children[ch];
}
node->isWord = true;
}
string findPrefix(string word){
string prefix;
trie* node = root;
for(char ch : word){
ch -= 'a';
if(node->children[ch] == nullptr){
break;
}
prefix += ch + 'a';
node = node->children[ch];
if(node->isWord){
return prefix;
}
}
return word;
}
};
这道题我们可以先将dictionary里的词根用Trie树来储存,并且我们用一个布尔值isWord来判断某一个节点是否是一个词根的结尾。
接下来我们自定义一个split函数用来将sentence的单词储存到vector的words中,接下来我们定义一个findPrefix函数,将words中的每一个word在字典树中进行查找,看有没有词根,如果有的话就返回词根,否则返回word自身。这样子我们的ans中储存的就是替换过的单词。
由于我们最后要返回的是一个句子,那么我们就将ans中的单词中插入空格,储存到res中,最后返回res即可。