LeetCode648. 单词替换
题目描述
本题目来自LeetCode上的『648. 单词替换』
在英语中,我们有一个叫做 词根
(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词
(successor)。例如,词根an
,跟随着单词 other
(其他),可以形成新的单词 another
(另一个)。
现在,给定一个由许多词根组成的词典 dictionary
和一个用空格分隔单词形成的句子 sentence
。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。
你需要输出替换之后的句子。
示例1:
输入:dictionary = [“cat”,”bat”,”rat”], sentence = “the cattle was rattled by the battery”
输出:”the cat was rat by the bat”
提示
1 <= dictionary.length <= 1000
1 <= dictionary[i].length <= 100
dictionary[i]
仅由小写字母组成。1 <= sentence.length <= 10^6
sentence
仅由小写字母和空格组成。sentence
中单词的总量在范围[1, 1000]
内。sentence
中每个单词的长度在范围[1, 1000]
内。sentence
中单词之间由一个空格隔开。sentence
没有前导或尾随空格。
题解
将词根保存到字典树中,每次匹配句子中的一个单词,首先匹配成功的一定是最短的词根。为了方便,当 node->isEnd = true
时保存对应的词根。
代码
class Trie {
private:
bool isEnd;
string word;
vector<Trie*> children;
public:
Trie() : children(26), isEnd(false) {}
void insert(const string& word) {
Trie* node = this;
for (const auto& ch: word) {
int idx = ch - 'a';
if (node->children[idx] == nullptr) {
node->children[idx] = new Trie();
}
node = node->children[idx];
}
node->isEnd = true;
node->word = word;
}
string search(const string& word) {
Trie* node = this;
for (const auto& ch: word) {
int idx = ch - 'a';
if (node->children[idx] == nullptr) {
return word;
}
node = node->children[idx];
if (node->isEnd) {
return node->word;
}
}
return word;
}
};
class Solution {
private:
vector<string> split(const string& s, const string& delimiters = " ") {
vector<string> ans;
string::size_type lastPos = s.find_first_not_of(delimiters, 0);
string::size_type pos = s.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos) {
ans.emplace_back(s.substr(lastPos, pos - lastPos));
lastPos = s.find_first_not_of(delimiters, pos);
pos = s.find_first_of(delimiters, lastPos);
}
return ans;
}
public:
string replaceWords(vector<string>& dictionary, string sentence) {
Trie* root = new Trie();
vector<string> token = split(sentence);
string ans;
for (const auto& word: dictionary) {
root->insert(word);
}
for (const auto& word: token) {
ans += root->search(word);
ans += ' ';
}
ans.pop_back();
return ans;
}
};
复杂度分析
设 $m$ 为词根的字符数, $n$ 为句子的长度。
- 时间复杂度:$O(m+n)$
- 空间复杂度:$O(m+n)$