【问题标题】:Check if a string contains an elemewnt in a large list quickly using a tree使用树快速检查字符串是否包含大列表中的 elemewnt
【发布时间】:2021-12-12 08:04:06
【问题描述】:

我有一个大的短字符串(单词)列表,我想检查它们中的任何一个是否出现在另一个字符串(句子)中。请注意,我不关心实际的单词/空格/标点符号/等。

这是python中典型的解决方案:

def contains_one_of(sentence, words):
    for word in words:
        if word in sentence:
            return word
    return None

我见过一些 python one-liners 做同样的事情,但从算法上我能找到的一切似乎基本上都是为所有元素调用 contains 函数。我假设 contains 函数使用一种滑动窗口方法。

我估计复杂度大约是 O(nmo)

其中 n = 列表长度,m = 句子长度,o = 列表中单词的平均长度

对我来说,我认为这可以通过一棵树来改进,但我找不到对这种算法的任何参考。 我基本上设想单词数组变成一棵树,其中一个节点是一个字母,它的所有子节点都是该单词的下一个字母。只要单词简短并且有合理的重叠,我认为这会更有效。

我已经在 python 中实现了这个版本,但我更愿意使用一个利用 C 来比较所有这些字符的包。 如果您知道此算法的名称或执行此操作的软件包的名称,我很想知道

这是我的版本,我相信很多都可以优化,但我想知道我是否在这里做一些事情。

sentence = "hello there cat, welcome home"
words = ["cat", "car", "cam", "arm", "ace", "arc"]

# build a dict tree per letter
def build_tree(patterns):
    root = dict()
    for p in patterns:
        r = root
        for i, c in enumerate(p):
            if c not in r:
                if i >= len(p) - 1: # last element
                    r[c] = p
                else: # any other element
                    r[c] = dict()
            r = r[c]
    return root
            
# Check if the substring starts with a path through the tree
def starts_with_tree(sub, tree):
    level = tree
    for c in sub:
        if c not in level: # nowhere left to go
            return None
        elif isinstance(level[c], str): # if we found a string we are at the end
            return level[c]
        else:
            level = level[c] # go deeper
            

# Check if s contains any path through the tree
def contains_which(s, root):
    for i in range(len(s)):
        sub = s[i:] # A substring missing the first i characters
        result = starts_with_tree(sub, root) 
        if result:
            return result
    return None
        

# build the tree
tree_root = build_tree(words)
print(tree_root)
# search within tree
found = contains_which(sentence, tree_root)
print("Found:", found)

【问题讨论】:

  • 您似乎正在寻找全文搜索功能。在这种情况下,您需要一个倒排索引数据结构。

标签: python algorithm tree contains


【解决方案1】:

你可以使用aho-corasick算法。

它使用 trie 结构(一种树),时间复杂度只是 O(m + o*n)(根据您的定义)(所有字符串长度总和的线性时间复杂度)

如果你不熟悉这个算法,那么它的实现是相当复杂的。所以你可以使用 python 库来实现 aho-corasick pyahocorasick

更多细节

Wikipedia

python aho-corasick library

【讨论】:

  • 宾果游戏!我想这正是我所追求的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
  • 2017-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多