解法
其实暴力也过了,行吧,学习一下如何优雅地使用python
解法一:前缀HASH
因为dict数组长1000,而root只长100,每次枚举单词长度小于100的前缀,看它是不是在dict里
class Solution(object):
def replaceWords(self, dict, sentence):
"""
:type dict: List[str]
:type sentence: str
:rtype: str
"""
dict = set(dict)
sentence = sentence.split(" ")
for i, word in enumerate(sentence):
for j in xrange(1, 100):
if word[:j] in dict:
sentence[i] = word[:j]
break
return " ".join(sentence)
解法二:Trie
这神奇的Trie实现方法真是让人涨见识辽
class Solution(object):
def replaceWords(self, roots, sentence):
"""
:type dict: List[str]
:type sentence: str
:rtype: str
"""
# 因为defaultdict注册的默认构造函数只有第一次调用的时候才会真正地调用,所以这里可以用自己来定义自己
# Trie是一个函数,调用它会返回一个defaultdict
Trie = lambda:collections.defaultdict(Trie)
# tri第一次调用Trie,返回了一个defalutdict,所以tri是个defalutdict
tri = Trie()
END = True
for root in roots:
# dict.__getitem__需要两个参数,第一个是字典对象,第二个是key
# 最开始,字典对象是tri,key是root的第一个字符c,tri[c]会返回一个新字典
# 新字典代表着该节点以字符c为开头的子节点
# 以此类推,最后得到一个叶子结点,它是默认应该是空的,我们给它的key为END的地方赋上整个单词的值
reduce(dict.__getitem__, root, tri)[END] = root
def replace(word):
cur = tri
for c in word:
# 要么这个字符不在当前节点的后继节点里,要么已经遇到了最短的前缀
if c not in cur or END in cur:break
# 否则继续往下遍历
cur = cur[c]
# 返回时有两种可能,如果cur没有对应的前缀,那么说明word没有匹配的单词,返回word
# get操作不会影响Trie的值
return cur.get(END, word)