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

无额外模块下优化大规模字符串多子串重叠出现次数统计方案问询

优化方案

核心耗时原因

你当前的方案是每个待统计子串单独调用find遍历主串,65万次find调用等价于将超大主串重复遍历了数十万次,这是耗时过高的根本原因。

分场景优化方案

场景1:所有待统计子串长度一致

直接滑动窗口单次遍历主串,统计所有对应长度的子串出现次数,仅需遍历主串1次,时间复杂度为O(N)(N为主串长度),实现代码如下:

# 提前收集所有待统计的子串,存为集合用于快速判断
target_temps = set(你所有的待统计子串列表)
L = len(next(iter(target_temps)))  # 所有子串统一长度
n = len(txt)
diz = {}

# 单次滑动窗口遍历
for i in range(n - L + 1):
    current_sub = txt[i:i+L]
    if current_sub in target_temps:
        if current_sub not in diz:
            diz[current_sub] = 0
        diz[current_sub] += 1

该方案在超大文本场景下也能轻松将耗时控制在1秒以内。

场景2:待统计子串长度不统一

自行实现轻量Aho-Corasick(AC)自动机,仅需遍历主串1次即可统计所有子串的重叠出现次数,无需重复遍历主串,纯Python实现无需依赖第三方模块,核心实现代码如下:

class ACNode:
    def __init__(self):
        self.children = {}
        self.fail = None
        self.output = []  # 存储以当前节点结尾的所有子串

def build_automaton(patterns):
    root = ACNode()
    # 构建前缀树
    for pattern in patterns:
        node = root
        for c in pattern:
            if c not in node.children:
                node.children[c] = ACNode()
            node = node.children[c]
        node.output.append(pattern)
    # 构建失败指针
    queue = []
    for child in root.children.values():
        child.fail = root
        queue.append(child)
    while queue:
        current_node = queue.pop(0)
        for c, child in current_node.children.items():
            fail_node = current_node.fail
            while fail_node is not None and c not in fail_node.children:
                fail_node = fail_node.fail
            child.fail = fail_node.children[c] if fail_node else root
            if child.fail:
                child.output.extend(child.fail.output)
            queue.append(child)
    return root

def ac_search(root, txt):
    count_dict = {}
    current = root
    for c in txt:
        while current is not None and c not in current.children:
            current = current.fail
        current = current.children[c] if current else root
        # 累计所有匹配到的子串
        for pattern in current.output:
            if pattern not in count_dict:
                count_dict[pattern] = 0
            count_dict[pattern] += 1
    return count_dict

# 调用示例
diz = ac_search(build_automaton(你所有的待统计子串列表), txt)

优化效果验证

上述两种方案都仅需遍历主串1次,避免了数十万次find调用带来的重复遍历开销,针对GB级以内的文本和数十万级的子串量,都能将耗时控制在1秒以内,完全满足性能要求。

内容的提问来源于stack exchange,提问作者EddyIT

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 11:54:09