我正在构建一个非常不兼容的二进制文件的解码器,我需要搜索二进制文件(特别是一个部分字节缓冲区,可能会选择4kB)用于帧头。这意味着使用有效的多模式字符串搜索算法。我决定了aho-corasick。问题是一些标题是部分字节,即11位。这些是我提出的方法:
修改aho-corasick trie以将子项存储在间隔树而不是哈希中。因此,给定示例模式0b11111111111
,第一个节点将存储范围[0xff-0xff]
,第二个节点将存储范围[0xe0-0xff]
。不幸的是,这极大地扩展了trie节点之间的后缀链接和字典后缀链接的数量,因此我认为此解决方案等同于以下解决方案:
将部分字节模式扩展为所有可能的匹配字节模式:0b11111111111
- > [0xffe0, 0xffe1, ..., 0xfffe, 0xffff]
。显然,增加可能的模式数量会大大增加搜索时间。
使用bitarray
模块将字节转换为位(各个位仍然由内存中的字节支持,但现在可以单独访问)。不幸的是,这会使搜索空间增加8倍,搜索模式的长度也会增加。
将模式截断为字节的倍数(即0b11111111111
- > 0b11111111
),然后使用标准整数位移来手动检查剩余的三个位。这大大增加了搜索空间中模式出现的次数。
我是否认为所有这些方法都具有完全相同的Big-Theta复杂性? ......或者一种方法更有效率?
Aho-corasick复杂度为O(n + m + z),其中n是搜索文本的长度,m是所有搜索模式的总长度,z是匹配数。 Aho-corasick检测到重叠的图案,这是不必要的,但由于我的图案没有重叠,所以不会发生。