【数据结构-Trie树】力扣648. 单词替换

在英语中,我们有一个叫做 词根(root) 的概念,可以词根 后面 添加其他一些词组成另一个较长的单词------我们称这个词为 衍生词 (derivative)。例如,词根 help,跟随着 继承词 "ful",可以形成新的单词 "helpful"。

现在,给定一个由许多 词根 组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有 衍生词 用 词根 替换掉。如果 衍生词 有许多可以形成它的 词根,则用 最短 的 词根 替换它。

你需要输出替换之后的句子。

示例 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"

提示:

1 <= dictionary.length <= 1000

1 <= dictionary[i].length <= 100

dictionary[i] 仅由小写字母组成。

1 <= sentence.length <= 106

sentence 仅由小写字母和空格组成。

sentence 中单词的总量在范围 [1, 1000] 内。

sentence 中每个单词的长度在范围 [1, 1000] 内。

sentence 中单词之间由一个空格隔开。

sentence 没有前导或尾随空格。

字典树

csharp 复制代码
class Solution {
private:
    struct trie{
        vector<trie*> children;
        bool isWord;
        trie(): children(26, nullptr), isWord(false){};
    };
    trie* root;

    vector<string> split(const string& sentence, char del){
        vector<string> result;
        string word;
        for(char c : sentence){
            if(c == del){
                if(!word.empty()){
                    result.push_back(word);
                    word.clear();
                }
            }
            else{
                word += c;
            }
        }
        if(!word.empty()){
            result.push_back(word);
        }
        return result;
    }

public:
    Solution(){
        root = new trie();
    }

    string replaceWords(vector<string>& dictionary, string sentence) {
        for(string word : dictionary){
            add(word);
        }

        vector<string> words = split(sentence, ' ');
        vector<string> ans;

        for(string word : words){
            ans.push_back(findPrefix(word));
        }
        
        string res;
        for(int i = 0; i < ans.size() - 1; i++){
            res += ans[i];
            res += ' ';
        }
        res += ans[ans.size() - 1];
        return res;
    }

    void add(string word){
        trie* node = root;
        for(char ch : word){
            ch -= 'a';
            if(node->children[ch] == nullptr){
                node->children[ch] = new trie();
            }
            node = node->children[ch];
        }
        node->isWord = true;
    }

    string findPrefix(string word){
        string prefix;
        trie* node = root;
        for(char ch : word){
            ch -= 'a';
            if(node->children[ch] == nullptr){
                break;
            }
            prefix += ch + 'a';
            node = node->children[ch];
            if(node->isWord){
                return prefix;
            }
        }
        return word;
    }
};

这道题我们可以先将dictionary里的词根用Trie树来储存,并且我们用一个布尔值isWord来判断某一个节点是否是一个词根的结尾。

接下来我们自定义一个split函数用来将sentence的单词储存到vector的words中,接下来我们定义一个findPrefix函数,将words中的每一个word在字典树中进行查找,看有没有词根,如果有的话就返回词根,否则返回word自身。这样子我们的ans中储存的就是替换过的单词。

由于我们最后要返回的是一个句子,那么我们就将ans中的单词中插入空格,储存到res中,最后返回res即可。

相关推荐
hb_zhyu4 小时前
Acwing.基础课.排列数字(c++题解)
数据结构·c++·算法
Swift社区5 小时前
LeetCode - #196 删除重复的电子邮件并保留最小 ID 的唯一电子邮件
vue.js·算法·leetcode·swift
一丝晨光5 小时前
为什么会有函数调用参数带标签的写法?Swift函数调用的参数传递需要加前缀是否是冗余?函数调用?函数参数?
java·开发语言·c++·ios·c#·objective-c·swift
江妍code6 小时前
数据结构:树和二叉树概念_堆篇
数据结构·数据库
axxy20008 小时前
C++ Primer Plus第六章课后习题总结
数据结构·c++·算法
�时过境迁,物是人非9 小时前
C#中的if判断语句详解
java·前端·c#
OpenC++9 小时前
【MySQL】常用语句
数据库·经验分享·笔记·mysql·leetcode·oracle
Ning_.10 小时前
LeetCode 151. 反转字符串中的单词
算法·leetcode·职场和发展