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 theroot
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"
题意:用字典中存在的前缀代替句子中的单词,若有多个前缀可以表示单词,则选择最短的一个
用基础字典树即可解决,将字典中的前缀字符串存入字典树中,遍历每个句子的单词,找到最短的前缀返回即可
字典树结构:
struct Trie{
int val; //表示此位置是否有前缀结束
vector<Trie*> child;
Trie():child(vector<Trie*>(26,NULL)),val(-1){}
};
首先是字典树的创建(插入)过程,题目只要返回最短的前缀字符串,在插入时对于每一个字符串的最后一个字符节点的val设置为0表示此位置为结束位置。
void insert(string s,Trie* root){
for(int i=0;i<s.size();i++){
int num = s[i]-'a';
if(root->child[num] == NULL)
{
root->child[num] = new Trie();
}
root = root->child[num];
if(i!=s.size()-1&&root->val!=0)
root->val = 1;
else root->val = 0; //若此位置为结束位置,将val设置为0
}
}
查找时,遇到val为0的字符节点就可以返回,这样就能保证返回的前缀为最短的,若字典树中不存在此单词的前缀,那么查找停止位置的val不等于0;
string search(string s,Trie* root){
string res = "";
for(int i=0;i<s.size();i++){
int num = s[i] -'a';
if(root->child[num] == NULL)
break;
root = root->child[num];
res += s[i];
if(root->val == 0)
return res;
}
if(root->val == 0)
return res;
else return s;
}
string replaceWords(vector<string>& dict, string sentence) {
Trie *root = new Trie();
string res = "";
for(string s:dict)
insert(s,root);
stringstream ss(sentence);
string s;
int sign = 1;
while(ss>>s){
string temp = search(s,root);
if(sign!=1)
res += " ";
if(temp.empty())
res +=s;
else res +=temp;
sign++;
}
return res;
}