我有一个字符串列表,例如:
py
python
co
comp
computer
我只想获得一个包含最大可能前缀量的字符串。结果应该是'计算机',因为它的前缀是'co'和'comp'(2个前缀)。
我有这个代码(wordlist是一个字典):
for i in wordlist:
word = str(i)
for j in wordlist:
if word.startswith(j):
wordlist[i] += 1
result = max(wordlist, key=wordlist.get)
有没有更好,更快的方法呢?
答案 0 :(得分:1)
您要查找的数据结构称为trie。关于这种搜索树的维基百科文章当然值得一读。这里派上用场的关键属性是:
节点的所有后代都有与该节点关联的字符串的公共前缀,并且根与空字符串相关联。
代码可能如下所示:
words = """py
python
co
comp
computer""".split()
def make_trie(ws):
"""Build trie from word list `ws`."""
r = {} # trie root
for w in ws:
d = r
for c in w:
d = d.setdefault(c, {}) # get c, set to {} if missing
d['$'] = '$' # end marker
return r
def num_pref(t, ws):
"""Use trie `t` to find word with max num of prefixes in `ws`."""
b, m = -1, '' # max prefixes, corresp. word
for w in ws:
d, p = t, 1
for c in w:
if '$' in d: p += 1
d = d[c] # navigate down one level
if p > b: b, m = p, w
return b, m
t = make_trie(words)
print(num_pref(t, words))
make_trie
构建了trie,num_pref
使用它来确定具有最大前缀数的单词。它会打印(3, 'computer')
。
显然,这两种方法可以结合起来。我将它们分开,以使构建特里的过程更加清晰。
答案 1 :(得分:0)
答案 2 :(得分:0)
“正确”的方式是使用某种特里数据结构或类似方法。但是,如果您的单词已经排序,那么实际上可以通过一些使用前缀堆栈而不是强力搜索的相当简单的代码获得相当快的速度。这是有效的,因为按排序顺序,所有前缀都在它们的前缀字之前(通过简单的线性扫描很容易得到结果)。可以把它想象成简单代码和高效代码之间的合理折衷:
prefixes = [] # Stack of all applicable prefixes up to this point (normally very small)
max_prefixes = [None]
for w in sorted(wordlist):
while prefixes and not w.startswith(prefixes[-1]):
prefixes.pop()
prefixes.append(w)
if len(prefixes) >= len(max_prefixes):
max_prefixes = list(prefixes)
result = max_prefixes[-1]
在我的Linux机器上运行所有词典单词(479828),上面的代码只需0.68秒(原始代码在合理的时间内没有完成)。在前10000个单词中,我的代码采用原始代码采用的 0.02s而不是19.5s 。
如果你想要真正高效的代码(比如,你正在处理千兆字节的数据),你最好使用在C中以缓存友好的方式编码的正确数据结构。但这可能需要数周才能正确写出来!