【发布时间】:2020-05-15 09:05:22
【问题描述】:
给定一个单词和一个词汇表,我想在词汇表中找到所有具有最长公共前缀的条目。
这里有一些例子:
> vocabulary = {"english", "englishx", "english-indian", "enya", "spanish"}
> prefix, words = find_by_longest_prefix(vocabulary, "englishy")
english: ['englishx', 'english', 'english-indian']
> prefix, words = find_by_longest_prefix(vocabulary, "entomology")
en: ['enya', 'englishx', 'english', 'english-indian']
> prefix, words = find_by_longest_prefix(vocabulary, "spania
spani: ['spanish']
现在想象一下,对于不同的输入词但相同的词汇,您必须多次调用此方法。我的幼稚实现在 O(n) 时间内找到匹配的单词(n 是输入单词的长度),但占用大量内存:O(n*m),其中 n 是词汇的大小,m 是最长的长度词汇表中的单词。
from collections import defaultdict
def build_words_by_prefix(vocabulary):
words_by_prefix = defaultdict(list)
for word in vocabulary:
for i in range(1, len(word) + 1):
prefix = word[:i]
words_by_prefix[prefix].append(word)
return words_by_prefix
def find_by_longest_prefix(vocabulary, word):
words_by_prefix = build_words_by_prefix(vocabulary)
for i in range(len(word)+1, 1, -1):
prefix = word[:i]
words = words_by_prefix.get(prefix, False)
if words:
return prefix, words
return False
我正在寻找一种既节省内存又节省时间的解决方案。我听说过 tries 可以更有效地存储前缀,但我想知道如何在这里使用它们?
【问题讨论】:
-
您可以使用名为“trie”的树形结构来表示词汇表。见How to create a trie in Python
-
非常感谢@Asocia 的讨论。我在问题中添加了一些附加信息。
-
您可能应该只是将单词放在排序列表中并进行二进制搜索。它会比在 python 中走一条树更快更紧凑。
-
@MattTimmermans 好点。看起来这可以使用内置的 bisect python 来实现:stackoverflow.com/questions/7380629/…