加载中...
648-单词替换(Replace Words)
发表于:2021-12-03 | 分类: 中等
字数统计: 1.4k | 阅读时长: 7分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/replace-words

英文原文

In English, we have a concept called root, which can be followed by some other word to form another longer word - let's call this word successor. For example, when the root "an" is followed by the successor word "other", we can form a new word "another".

Given a dictionary consisting of many roots and a sentence consisting of words separated by spaces, replace all the successors in the sentence with the root forming it. If a successor can be replaced by more than one root, replace it with the root that has the shortest length.

Return the sentence after the replacement.

 

Example 1:

Input: dictionary = ["cat","bat","rat"], sentence = "the cattle was rattled by the battery"
Output: "the cat was rat by the bat"

Example 2:

Input: dictionary = ["a","b","c"], sentence = "aadsfasf absbs bbab cadsfafs"
Output: "a a b c"

Example 3:

Input: dictionary = ["a", "aa", "aaa", "aaaa"], sentence = "a aa a aaaa aaa aaa aaa aaaaaa bbb baba ababa"
Output: "a a a a a a a a bbb baba a"

Example 4:

Input: dictionary = ["catt","cat","bat","rat"], sentence = "the cattle was rattled by the battery"
Output: "the cat was rat by the bat"

Example 5:

Input: dictionary = ["ac","ab"], sentence = "it is abnormal that this solution is accepted"
Output: "it is ab that this solution is ac"

 

Constraints:

  • 1 <= dictionary.length <= 1000
  • 1 <= dictionary[i].length <= 100
  • dictionary[i] consists of only lower-case letters.
  • 1 <= sentence.length <= 10^6
  • sentence consists of only lower-case letters and spaces.
  • The number of words in sentence is in the range [1, 1000]
  • The length of each word in sentence is in the range [1, 1000]
  • Each two consecutive words in sentence will be separated by exactly one space.
  • sentence does not have leading or trailing spaces.

中文题目

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

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

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

 

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

示例 3:

输入:dictionary = ["a", "aa", "aaa", "aaaa"], sentence = "a aa a aaaa aaa aaa aaa aaaaaa bbb baba ababa"
输出:"a a a a a a a a bbb baba a"

示例 4:

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

示例 5:

输入:dictionary = ["ac","ab"], sentence = "it is abnormal that this solution is accepted"
输出:"it is ab that this solution is ac"

 

提示:

  • 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 没有前导或尾随空格。

通过代码

官方题解

方法一:前缀哈希【通过】

思路

遍历句子中每个单词,查看单词前缀是否为词根。

算法

将所有词根 roots 存储到集合 Set 中。遍历所有单词,判断其前缀是否为词根。如果是,则使用前缀代替该单词;否则不改变该单词。

[solution1-Python]
def replaceWords(self, roots, sentence): rootset = set(roots) def replace(word): for i in xrange(1, len(word)): if word[:i] in rootset: return word[:i] return word return " ".join(map(replace, sentence.split()))
[solution1-Java]
class Solution { public String replaceWords(List<String> roots, String sentence) { Set<String> rootset = new HashSet(); for (String root: roots) rootset.add(root); StringBuilder ans = new StringBuilder(); for (String word: sentence.split("\\s+")) { String prefix = ""; for (int i = 1; i <= word.length(); ++i) { prefix = word.substring(0, i); if (rootset.contains(prefix)) break; } if (ans.length() > 0) ans.append(" "); ans.append(prefix); } return ans.toString(); } }

复杂度分析

  • 时间复杂度:$O(\sum w_i^2)$,其中 $w_i$ 是第 $i$ 个单词的长度。检查第 $i$ 个单词的所有前缀花费时间 $O(w_i^2)$。

  • 空间复杂度:$O(N)$,其中 $N$ 是句子的长度,词根使用 rootset 存储。

方法二:前缀树【通过】

思路和算法

把所有的词根放入前缀树中,在树上查找每个单词的最短词根,该操作可在线性时间内完成。

[solution2-Python]
class Solution(object): def replaceWords(self, roots, sentence): Trie = lambda: collections.defaultdict(Trie) trie = Trie() END = True for root in roots: reduce(dict.__getitem__, root, trie)[END] = root def replace(word): cur = trie for letter in word: if letter not in cur or END in cur: break cur = cur[letter] return cur.get(END, word) return " ".join(map(replace, sentence.split()))
[solution2-Java]
class Solution { public String replaceWords(List<String> roots, String sentence) { TrieNode trie = new TrieNode(); for (String root: roots) { TrieNode cur = trie; for (char letter: root.toCharArray()) { if (cur.children[letter - 'a'] == null) cur.children[letter - 'a'] = new TrieNode(); cur = cur.children[letter - 'a']; } cur.word = root; } StringBuilder ans = new StringBuilder(); for (String word: sentence.split("\\s+")) { if (ans.length() > 0) ans.append(" "); TrieNode cur = trie; for (char letter: word.toCharArray()) { if (cur.children[letter - 'a'] == null || cur.word != null) break; cur = cur.children[letter - 'a']; } ans.append(cur.word != null ? cur.word : word); } return ans.toString(); } } class TrieNode { TrieNode[] children; String word; TrieNode() { children = new TrieNode[26]; } }

复杂度分析

  • 时间复杂度:$O(N)$,其中 $N$ 是 sentence 的长度。每次查询操作为线性时间复杂度。

  • 空间复杂度:$O(N)$,前缀树的大小。

统计信息

通过次数 提交次数 AC比率
22811 38772 58.8%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言

相似题目

题目 难度
实现 Trie (前缀树) 中等
上一篇:
647-回文子串(Palindromic Substrings)
下一篇:
650-只有两个键的键盘(2 Keys Keyboard)
本文目录
本文目录