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)基于哈希表的朴素查找法
2)基于前缀树的最短前缀匹配解法
解法1的思路很直观,即将dictionary中所有的单词放在Hash Table中,然后依次匹配sentence中的每个单词。在匹配时,从每个单词中自左向右滑动窗口取其前缀,然后再Hash Table中进行查找,取最短的即可。
class Solution:
def replaceWords(self, dictionary: List[str], sentence: str) -> str:
dictionarySet = set(dictionary)
words = sentence.split(' ')
for i, word in enumerate(words):
# find shortest prefix of the word brutely
for j in range(1, len(words) + 1):
if word[:j] in dictionarySet:
words[i] = word[:j]
break
return ' '.join(words)
解法2的思路也不复杂,它就是先基于dictionary构造Trie树,然后依次在字典树中匹配sentence中的每个单词的最短前缀,最后将所有前缀拼接起来即可。
class Trie:
def __init__(self):
self.children = [None] * 26
self.isEnd = False
def insert(self, word: str) -> None:
node = self
for ch in word:
ch = ord(ch) - ord("a")
if not node.children[ch]:
node.children[ch] = Trie()
node = node.children[ch]
node.isEnd = True
class Solution:
def replaceWords(self, dictionary: List[str], sentence: str) -> str:
trie = Trie()
for word_root in dictionary:
trie.insert(word_root)
words = sentence.split(' ')
for idx, word in enumerate(words):
cur = trie
# Find the shortest prefix and replace the word as it
for j, ch in enumerate(word):
if cur.isEnd:
words[idx] = word[:j] # a valid prefix
break
# Check whether it has child node or not
ch = ord(ch) - ord("a")
if not cur.children[ch]:
break
cur = cur.children[ch]
return ' '.join(words)
关于前缀树的实现可查看文章 Leetcode 208 实现前缀树。