You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用树结构快速检查字符串是否包含大列表中短字符串的方案咨询

问题背景

我有一个由短字符串(单词)组成的大列表,需要检查其中是否有任意元素出现在另一个目标字符串(句子)中,不需要区分实际单词边界、空格、标点符号等内容。

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

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

我见过一些实现相同功能的Python单行写法,但从算法层面来看,我能找到的所有实现基本都是对所有元素逐一调用包含检测函数,我推测这类包含检测函数底层采用滑动窗口类的实现逻辑。
按照我的测算,这类方案的时间复杂度约为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)

解答

你的思路完全正确,你自己实现的这个树结构就是前缀树(Trie 树),专门用于高效处理多字符串匹配、前缀查询类的场景。
如果还要进一步优化查询效率,可以用基于前缀树升级的Aho-Corasick算法(简称AC自动机),它在查询时不需要对每个句子的起始位置单独遍历,时间复杂度可以降到O(m + k),其中m是句子长度,k是匹配到的结果数量,比你现在的实现效率更高,非常适合大词表下的多模式匹配场景。
如果要找底层用C实现的高性能Python包,可以用pyahocorasick,这个包是AC自动机的工业级实现,性能远高于纯Python写的前缀树版本,使用也很简单。
另外你现有的纯Python实现有个小问题:如果存在一个单词是另一个单词的前缀的情况(比如词表里同时有cat和cater),你的逻辑会提前返回短的单词,不会匹配到更长的,如果你有匹配最长词的需求需要调整终止节点的判断逻辑。


内容的提问来源于stack exchange,提问作者M'Goops

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 20:15:07