刚开始一直在用哈希,结果超时了,然后再开了一个哈希表优化了一下,没想到还是超时。左思右想想不到其它方法,看了题解才知道可以用字典树。前缀+字符串,这不是妥妥的字典树吗,看来是字典树的知识都快忘完了。
思路:构建一棵前缀树,开一个26大小的结构体数组来存储,每经过一个节点就在该节点的位置加1,表示以该节点结尾的前缀单词的数量。
class Solution {
struct Trie{
int val;
Trie* trie[26];
Trie(){
val = 0;
for(int i = 0; i < 26; i++)
trie[i] = nullptr;
}
};
public:
vector<int> sumPrefixScores(vector<string>& words) {
vector<Trie*> t(26);
for(string word: words){
if(t[word[0] - 'a'] == nullptr)
t[word[0] - 'a'] = new Trie();
auto now = t[word[0]-'a'];
for(int i = 1; i < word.size(); i++){
now->val++;
if(now->trie[word[i]-'a'] == nullptr)
now->trie[word[i]-'a'] = new Trie();
now = now->trie[word[i]-'a'];
}
now->val++;
}
vector<int> res;
for(string word : words){
auto now = t[word[0]-'a'];
int sum = 0;
for(int i = 1; i < word.size(); i++){
sum +=now->val;
now = now->trie[word[i]-'a'];
}
sum += now->val;
res.push_back(sum);
}
return res;
}
};
趁热打铁
题意:将一个句子中的所有单词替换为该单词的词根。
思路:根据所有的词根构建一棵前缀树,然后拿到句子的每个单词去遍历,如果遍历到的节点是词根的节点,那么用这个词根替换原句子中的单词。
class Solution {
struct Trie{
bool is_end; //该节点是否为词根的结尾
Trie* trie[26];
Trie(){
is_end = false;
for(int i = 0; i < 26; i++)
trie[i] = nullptr;
}
};
Trie* root = new Trie();
public:
void buildTree(vector<string>& dictionary){
for(string s: dictionary){
Trie* node = root;
for(char c: s){
if(!node->trie[c-'a'])
node->trie[c-'a'] = new Trie();
node = node->trie[c-'a'];
}
node->is_end = true;
}
}
string search(string str){
Trie* node = root;
int index = 0;
for(char c : str){
//找最短的词根
if(!node->trie[c-'a'] && !node->is_end) return str;
if(node->is_end ) return str.substr(0, index);
node = node->trie[c-'a'];
index++;
}
return str.substr(0, index);
}
string replaceWords(vector<string>& dictionary, string sentence) {
buildTree(dictionary);
string res = "";
string str = "";
for(int i = 0; i < sentence.size(); i++){
if(sentence[i] == ' ' ){
res += search(str) + ' ';
str = "";
}else{
str +=sentence[i];
}
}
res += search(str);
return res;
}
};