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 小时前
驾驶轨迹换个坐标,就能给移动机器人用吗?
人工智能·算法·机器学习
文丑颜不良啊5 小时前
LeetCode2461~2480题目解析
java·leetcode
文丑颜不良啊6 小时前
LeetCode2441~2460题目解析
java·leetcode
文丑颜不良啊7 小时前
LeetCode2521~2540题目解析
java·leetcode
lisw058 小时前
Dayhoff的PAM替换矩阵理论评介!
线性代数·算法·矩阵
一起学安全技术9 小时前
拆大模型 03|注意力的一句话版本:不用论文讲清 Attention
深度学习·算法·语言模型·transformer
Delightrs10 小时前
Rust LeetCode238 算法题解
开发语言·算法·rust
自信1504130575910 小时前
重生之从0开始学习c++之——vector-中篇
c++·学习·算法
文丑颜不良啊10 小时前
LeetCode2501~2520题目解析
java·leetcode
lsc_blog16 小时前
年终自评别贴提交记录,把技术产出讲成变化
数据库·面试·职场和发展·跳槽·求职招聘