题目描述
In English, we have a concept called root, which can be followed by some other words to form another longer word - let’s call this word successor. For example, the root an, followed by other, which can form another word another.
Now, given a dictionary consisting of many roots and a sentence. You need to replace all the successor in the sentence with the root forming it. If a successor has many roots can form it, replace it with the root with the shortest length.
You need to output the sentence after the replacement.
Example 1:
Input: dict = [“cat”, “bat”, “rat”]
sentence = “the cattle was rattled by the battery”
Output: “the cat was rat by the bat”
Note:
The input will only have lower-case letters.
1 <= dict words number <= 1000
1 <= sentence words number <= 1000
1 <= root length <= 100
1 <= sentence words length <= 1000
解决此题的关键是实现一个字典树。
C++ 实现
class Solution {
public:
string replaceWords(vector<string>& dict, string sentence) {
Trie trie;
trie.Init(dict);
stringstream res_stream;
// 利用stringstream 实现split 的效果
stringstream ss(sentence);
string word;
while(getline(ss, word, ' '))
{
res_stream << trie.PrefixLookup(word);
res_stream << " ";
}
string res = res_stream.str();
res.pop_back();
return res;
}
private:
class Trie
{
struct TrieNode
{
TrieNode(){}
TrieNode(const char val, const bool is_end)
: val(val), is_end(is_end), childrens(26, nullptr)
{
}
char val;
bool is_end;
std::vector<TrieNode*> childrens;
};
public:
Trie()
{
root = new TrieNode('0', false);
}
~Trie()
{
ReleaseTrie(root);
}
Trie(const Trie&) = delete;
Trie& operator = (const Trie&) = delete;
// 初始化字典树
void Init(const std::vector<std::string>& dict)
{
for (const std::string& word : dict)
{
Insert(word);
}
}
// 找到字典树中和word有相同前缀的最短的那个,
// 如果没有则直接返回word
std::string PrefixLookup(const std::string& word) const
{
TrieNode* cur = root;
std::string res = "";
for (const char c : word)
{
res += c;
if (cur->childrens[c - 'a'])
{
if (cur->childrens[c - 'a']->is_end)
{
return res;
}
cur = cur->childrens[c - 'a'];
}
else
{
return word;
}
}
return word;
}
private:
// 在字典树中插入一个word
void Insert(const std::string& word)
{
if (word.empty())
return;
TrieNode* cur = root;
for (const char c : word)
{
if (!cur->childrens[c - 'a'])
{
cur->childrens[c - 'a'] = new TrieNode(c, false);
}
cur = cur->childrens[c - 'a'];
}
cur->is_end = true;
}
// 递归释放内存
void ReleaseTrie(const TrieNode* root)
{
if (!root) return;
bool no_children = true;
const std::vector<TrieNode*>& childrens = root->childrens;
for (const TrieNode* children : childrens)
{
if (children)
{
no_children = false;
ReleaseTrie(children);
}
}
if (no_children)
{
delete root;
}
}
TrieNode* root;
};
};