LeetCode 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 <= dictionaryi.length <= 100

dictionaryi 仅由小写字母组成。

1 <= sentence.length <= 106^66

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

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

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

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

sentence 没有前导或尾随空格。

我们可以使用字典树,先把所有词根前缀存入字典树,然后对sentence中的每个单词查询是否在字典树中,如果在,就只保留前缀:

cpp 复制代码
class Node {
public:
    vector<Node *> next = vector<Node *>(26, nullptr);
    bool isEnd = false;
};

class Solution {
public:
    string replaceWords(vector<string>& dictionary, string sentence) {
        Node *root = new Node();
        // 存入字典树
        for (string s : dictionary) {
            Node *curNode = root;
            for (char c : s) {
                if (curNode->next[c - 'a'] == nullptr) {
                    curNode->next[c - 'a'] = new Node();
                }
                curNode = curNode->next[c - 'a'];
            }
            curNode->isEnd = true;
        }

        string ans;
        for (int i = 0; i < sentence.size(); ++i) {
            Node *curNode = root;
            while (i < sentence.size() && sentence[i] != ' ') {
                char c = sentence[i];
                // 逐字符字典树查找
                if (curNode->next[c - 'a'] != nullptr) {
                    ans += c;
                    curNode = curNode->next[c - 'a'];

                    // 如果是一个前缀
                    if (curNode->isEnd) {
                        break;
                    }
                } else {
                    break;
                }
                ++i;
            }

            while (i < sentence.size() && sentence[i] != ' ') {
                // 如果没找到词根前缀,就把单词完整放入答案
                if (!curNode->isEnd) {
                    ans += sentence[i];
                }

                ++i;
            }

            if (i < sentence.size() && sentence[i] == ' ') {
                ans += ' ';
            }
        }

        return ans;
    }
};

如果词缀中有n个字母,sentence的长度为m,则此算法时间复杂度为O(n+m),空间复杂度为O(n)。

相关推荐
一只积极向上的小咸鱼2 小时前
分词器tokenizer
算法·llm
Elsa️7462 小时前
leetcode 14.最长公共前缀
算法·leetcode·职场和发展
不会代码的小猴2 小时前
6. Qt网络编程
开发语言·c++·笔记·qt·算法
Zguigo2 小时前
树的前序|中序|后序遍历【使用栈实现】
数据结构·算法
zhanghaha13142 小时前
HTML系列教程:4_什么是 HTML 元素(零基础超详细讲解)
前端·算法·html
TAN-90°-2 小时前
Deep Learning for Computer Vision——Training CNNs and CNN Architectures
人工智能·深度学习·神经网络·算法·机器学习·计算机视觉·cnn
0x3F(小茶)2 小时前
Tokenization(分词算法):一切大语言模型的地基
人工智能·算法·语言模型
Keven_112 小时前
算法札记:利用floyd判环算法优化SPFA判负环算法
算法·spfa判负环
mCell11 小时前
Lua 编程入门:从基础语法到元表
javascript·算法·lua