【数据结构-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即可。

相关推荐
qq_513970444 小时前
力扣 hot100 Day56
算法·leetcode
唐青枫5 小时前
C#.NET dapper 详解
c#·.net
爱装代码的小瓶子6 小时前
数据结构之队列(C语言)
c语言·开发语言·数据结构
爱喝矿泉水的猛男7 小时前
非定长滑动窗口(持续更新)
算法·leetcode·职场和发展
YuTaoShao7 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
死也不注释7 小时前
【鸡零狗碎记录】
unity·c#
Maybe_ch7 小时前
.NET-键控服务依赖注入
开发语言·c#·.net
aramae9 小时前
大话数据结构之<队列>
c语言·开发语言·数据结构·算法
大锦终9 小时前
【算法】前缀和经典例题
算法·leetcode
cccc来财10 小时前
Java实现大根堆与小根堆详解
数据结构·算法·leetcode