关于python:从大字典中匹配子字符串的最快方法

Fastest way to match substring from large dict

我有一些(通常 < 300 个符号长度)字符串,例如 'aabbccdcabcbbacdaaa'。

有一个 python 字典,其中键是类似格式的字符串,例如'bcccd',密钥长度从 10 到 100 个符号不等。字典有 50 万个条目。

我需要将我的初始字符串与字典的值相匹配,或者找出字典中没有正确的值。匹配条件:字典键应该在字符串中的某处(严格匹配)。

就计算速度而言,最好的方法是什么?
我觉得应该有一些棘手的方法来散列我的初始字符串和字典键,以应用一些巧妙的子字符串搜索方法(如 Rabin-Karp 或 Knuth-Morris-Pratt)。或者后缀树状结构可能是一个很好的解决方案?


刚刚为 Python 找到了一个合理的 Aho-Corasick 实现 - pyahocorasick。取自页面末尾的示例:

1
2
3
4
5
6
7
8
9
import ahocorasick
A = ahocorasick.Automaton()

for k, v in your_big_dict.iteritems():
    A.add_word(k, v)

A.make_automaton()
for item in A.iter(your_long_string):
    print(item)


1
2
3
4
5
6
7
8
9
10
11
def search(string, dict_search):
    # If those 2 lines are too expensive, calculate them and pass as arguments
    max_key = max(len(x) for x in dict_search)
    min_key = min(len(x) for x in dict_search)

    return set(
        string[x:x+i]
        for i in range(min_key, max_key+1)
        for x in range(len(string)-i+1)
        if string[x:x+i] in dict_search
    )

跑步:

1
2
>>> search('aabbccdcabcbbacdaaa', {'aaa', 'acd', 'adb', 'bccd', 'cbbb', 'abc'})
{'aaa', 'abc', 'acd', 'bccd'}


您可以使用以下格式:

1
2
3
for key in your_dictionary:
    if key in your_string:
        print(key+' is in both your string and the dictionary. It has the value '+str(your_dictionary[key]))

如果您想以任何方式对此进行更改,请在评论中告诉我,我很乐意更新。