LeetCode648. 单词替换


LeetCode648. 单词替换

题目描述

本题目来自LeetCode上的『648. 单词替换』

在英语中,我们有一个叫做 词根(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。

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

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

示例1:

输入:dictionary = [“cat”,”bat”,”rat”], sentence = “the cattle was rattled by the battery”
输出:”the cat was rat by the bat”

提示
  • 1 <= dictionary.length <= 1000
  • 1 <= dictionary[i].length <= 100
  • dictionary[i] 仅由小写字母组成。
  • 1 <= sentence.length <= 10^6
  • sentence 仅由小写字母和空格组成。
  • sentence 中单词的总量在范围 [1, 1000] 内。
  • sentence 中每个单词的长度在范围 [1, 1000] 内。
  • sentence 中单词之间由一个空格隔开。
  • sentence 没有前导或尾随空格。

题解

将词根保存到字典树中,每次匹配句子中的一个单词,首先匹配成功的一定是最短的词根。为了方便,当 node->isEnd = true 时保存对应的词根。

代码

class Trie {
private:
    bool isEnd;
    string word;
    vector<Trie*> children;

public:
    Trie() : children(26), isEnd(false) {}

    void insert(const string& word) {
        Trie* node = this;
        for (const auto& ch: word) {
            int idx = ch - 'a';
            if (node->children[idx] == nullptr) {
                node->children[idx] = new Trie();
            }
            node = node->children[idx];
        }
        node->isEnd = true;
        node->word = word;
    }

    string search(const string& word) {
        Trie* node = this;
        for (const auto& ch: word) {
            int idx = ch - 'a';
            if (node->children[idx] == nullptr) {
                return word;
            }
            node = node->children[idx];
            if (node->isEnd) {
                return node->word;
            }
        }
        return word;
    }
};
class Solution {
private:
    vector<string> split(const string& s, const string& delimiters = " ") {
        vector<string> ans;
        string::size_type lastPos = s.find_first_not_of(delimiters, 0);
        string::size_type pos = s.find_first_of(delimiters, lastPos);
        while (string::npos != pos || string::npos != lastPos) {
            ans.emplace_back(s.substr(lastPos, pos - lastPos));
            lastPos = s.find_first_not_of(delimiters, pos);
            pos = s.find_first_of(delimiters, lastPos);
        }
        return ans;
    }
public:
    string replaceWords(vector<string>& dictionary, string sentence) {
        Trie* root = new Trie();
        vector<string> token = split(sentence);
        string ans;
        for (const auto& word: dictionary) {
            root->insert(word);
        }
        for (const auto& word: token) {
            ans += root->search(word);
            ans += ' ';
        }
        ans.pop_back();
        return ans;
    }
};

复杂度分析

设 $m$ 为词根的字符数, $n$ 为句子的长度。

  • 时间复杂度:$O(m+n)$
  • 空间复杂度:$O(m+n)$

文章作者: xitie2000
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 xitie2000 !
评论
  目录