leetcode 648 单词替换
648. 单词替换
在英语中,我们有一个叫做 词根(root)的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。
例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。
现在,给定一个由许多词根组成的词典和一个句子。你需要将句子中的所有继承词用词根替换掉。
如果继承词有许多可以形成它的词根,则用最短的词根替换它。
你需要输出替换之后的句子。
示例 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"
示例 3:
输入:dictionary = ["a", "aa", "aaa", "aaaa"], sentence = "a aa a aaaa aaa aaa aaa aaaaaa bbb baba ababa"
输出:"a a a a a a a a bbb baba a"
示例 4:
输入:dictionary = ["catt","cat","bat","rat"], sentence = "the cattle was rattled by the battery"
输出:"the cat was rat by the bat"
示例 5:
输入:dictionary = ["ac","ab"], sentence = "it is abnormal that this solution is accepted"
输出:"it is ab that this solution is ac"
思路1:
https://xiaoneng.blog.csdn.net/article/details/100593307
本题我们直接使用字符串流来讲句子划分为一个个单词,然后遍历数组,将句子中的每个单词与数组的元素进行比较。
对于使用前缀树,我们倒不如直接比较数组中元素第一个字符和单词的第一个字符效率来的快。
基本想法,就是将字典按照长度从小到大排序,然后再依次遍历单词去进行前缀匹配,如果匹配成功则替换;
class Solution { public: string replaceWords(vector<string>& dict, string sentence) { //将字典进行长度排序: auto cmp = [](string &s1, string &s2) { return s1.size() < s2.size(); }; sort(dict.begin(), dict.end(), cmp); istringstream line(sentence); string word,result=""; while(line>>word) { int i=0; for(;i<dict.size();++i) { //找到前缀词,将前缀词加到result中 if(dict[i][0]==word[0]&&word.substr(0,dict[i].size())==dict[i]){result+=dict[i]+" ";break;} } //没有找到前缀词,将原有的单词添加到result中 if(i==dict.size())result+=word+" "; } if(result.size()>0)result.resize(result.size()-1);//删除最后一个空格 return result; } };
思路2:字典树
我们根据字典中的单词构造字典树。然后获取句子中的每个单词,判断它有没有词根,有则直接替换。
思路参考:https://cloud.tencent.com/developer/article/1660012
Trie树讲解(写的很好):https://blog.csdn.net/qq_21201267/article/details/93513683
先将单词插入Trie树
然后依次查询每个单词的各前缀是否在Trie中,进行替换
class TrieNode//节点 { public: char ch; TrieNode *next[26]; bool isEnd; TrieNode(char c = '/'):ch(c),isEnd(false) { memset(next, 0, sizeof(TrieNode*)*26); } }; class Trie//Trie树 { public: TrieNode *root; Trie() { root = new TrieNode(); } ~Trie()//析构释放内存 { destroy(root); } void destroy(TrieNode *root) { if(root == NULL) return; for(int i = 0; i < 26; i++) destroy(root->next[i]); delete root; } void insert(string str)//插入单词 { TrieNode *cur = root; for(char s:str) { if(cur->next[s-'a'] == NULL) cur->next[s-'a'] = new TrieNode(s-'a'); cur = cur->next[s-'a']; } cur->isEnd = true; } }; class Solution { Trie tree; public: string replaceWords(vector<string>& dict, string sentence) { for(string s:dict) tree.insert(s); string word, ans, prefix; TrieNode *cur = tree.root; istringstream in(sentence); int i, chIdx; while(in >> word) { cur = tree.root; prefix = ""; for(i = 0; i < word.size(); ++i) { chIdx = word[i]-'a'; if(cur->next[chIdx] == NULL) { ans += word; break; } else { prefix.push_back(word[i]); if(cur->next[chIdx]->isEnd) { ans += prefix; break; } if(i == word.size()-1)//最后一个字符特殊处理 ans += prefix; } cur = cur->next[chIdx]; } ans.push_back(' '); } ans.pop_back();//删除空格 return ans; } };