将符号流与动态模式匹配

时间:2016-10-13 20:55:26

标签: string algorithm match string-matching

您如何实施以下问题的解决方案:
给定一串符号和模式,可以随时添加,计算每个模式出现的频率。

示例
有一连串的传入符号让我们说 A B A C D E ...... 用户可以随时注册新模式,例如(B A C)。如果在第二个时间步之前注册了模式,则应该对模式进行一次计数。

如果模式重叠,则只应计算第一个模式,例如(BAC)(ACD)仅导致(BAC)被计算在内。

解决方案
简单的解决方案是每个模式保持一个位置,在模式匹配时前进,并在匹配后重置所有位置。这将导致O(n * m)的运行时间 其中n是流的长度,m是最长模式的长度(例如,通过在所有模式中具有相同的长度m-1前缀)。

替代方法是构造有限自动机并使用模式可以具有组合前缀的事实。   Example automata

但是有一些问题:

  • 如何构建模式之间的边缘? (例如 B D E 来自 A B

  • 如何在运行时添加模式。例如。假设流是 A B ,目前只注册了模式(A B C)。现在用户注册(B A C)。如果流继续 A C D E 。由于第一个符号在注册之前发生,因此不应匹配该模式。

这个想法可以与Aho Corasick algorithm相关联。然而,该算法确实匹配所有出现的模式而不仅仅是第一个模式。它不允许在运行时添加模式。

1 个答案:

答案 0 :(得分:1)

保持最初为空的Aho-Corasick FSM列表。每当注册一个新模式时,只为该模式创建一个新的FSM,将其附加到列表中,并检查列表末尾是否有2个单字符串FSM:如果是,则删除它们,构建一个新模式两个字符串都使用FSM,并将此FSM替换为原始字符串。现在检查是否有2个2字符串FSM,如果是,则将它们组合成单个4字符串FSM。重复此过程,将两个k-string FSM组合成一个(2k)-string FSM,直到所有FSM都用于不同数量的字符串。 (请注意,相同数量的字符串的任何2个FSM必须位于列表中的相邻位置。)

假设总共发生了n次注册。由于上述“压缩”过程,该列表将始终包含最多log2(n)+1个FSM,因此使用每个这些FSM进行搜索的总体“成本因素”输入流(相对于包含所有字符串的单个FSM)是O(log n)。此外,特定字符串参与的FSM构建过程的数量上限为log2(n)+1,因为它参与构建的每个新FSM必须是它参与构建的前一个FSM的两倍。因此,构建所有FSM的整体“成本因素”(与构建包含所有字符串的单个FSM相比)也是O(log n)。