您如何实施以下问题的解决方案:
给定一串符号和模式,可以随时添加,计算每个模式出现的频率。
示例:
有一连串的传入符号让我们说 A B A C D E ......
用户可以随时注册新模式,例如(B A C)。如果在第二个时间步之前注册了模式,则应该对模式进行一次计数。
如果模式重叠,则只应计算第一个模式,例如(BAC)和(ACD)仅导致(BAC)被计算在内。
解决方案:
简单的解决方案是每个模式保持一个位置,在模式匹配时前进,并在匹配后重置所有位置。这将导致O(n * m)的运行时间
其中n是流的长度,m是最长模式的长度(例如,通过在所有模式中具有相同的长度m-1前缀)。
但是有一些问题:
如何构建模式之间的边缘? (例如 B D E 来自 A B )
如何在运行时添加模式。例如。假设流是 A B ,目前只注册了模式(A B C)。现在用户注册(B A C)。如果流继续 A C D E 。由于第一个符号在注册之前发生,因此不应匹配该模式。
这个想法可以与Aho Corasick algorithm相关联。然而,该算法确实匹配所有出现的模式而不仅仅是第一个模式。它不允许在运行时添加模式。
答案 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)。