【问题标题】:Data structure for large number of patterns大量模式的数据结构
【发布时间】:2015-06-29 00:02:45
【问题描述】:

在一次采访中,我被要求提出可以容纳数百万个模式的数据结构,并能够快速搜索它们以找到最长匹配的模式。

例如,模式如下:

1- 8876 8893 87          | true
2- 8876 889              | false
3- 8876 8                | false
4- 887                   | true

输入是一个至少2位最多18位的数字,我们需要从数据结构中找到最长的匹配模式,并在最后提取布尔值。

例如,8876 8893 9943 53 将匹配 1 并返回 true8876 8397 5430 74 将匹配 3 并返回 false

我的答案是使用一棵树并在每个级别都有一个key value 对列表。键是数字,值是 null 或等于布尔值,具体取决于它是否是模式的结尾。喜欢:

# matching 8875
# start the search by first digit
[..., (7, null), (8, null), (9, null)] 
                  ^
                 [..., (7, null), (8, null), (9, null)] 
                                   ^
                                   [..., (7, true), (8, null), ...]
# at the last step because we don't have a pattern 
# to match the digit 5, we return the `true` from (7, true)

具有挑战性的部分是,模式非常多。数以百万计。这有什么好处吗?如果没有,您的建议是什么。

【问题讨论】:

  • @Alex,纯金人。有时一个词打开了一个新世界。非常感谢。如果您想发布它,我什至会接受而不是作为答案。
  • 好的,我将其添加为答案,同时允许问题以接受的答案“关闭”。

标签: algorithm data-structures pattern-matching


【解决方案1】:

一个非常适合您描述的问题的非常好的数据结构,即一个集合结构,其中许多条目共享一个公共前缀(和/或后缀),并且您根据共享前缀执行搜索是Trie

computer science 中,一个trie,也称为digital tree,有时也称为radix treeprefix tree(因为它们可以被搜索到通过前缀),是一种有序的树数据结构,用于存储动态集合或关联数组,其中键通常是字符串。与二叉搜索树不同,树中没有节点存储与该节点关联的键;相反,它在树中的位置定义了与之关联的键。一个节点的所有后代都有一个与该节点关联的字符串的公共prefix,并且根与空字符串相关联。值通常不与每个节点相关联,仅与叶和一些与感兴趣的键对应的内部节点相关联。前缀树的空间优化表示见compact prefix tree

特别是紧凑前缀树或 patricia trie 似乎非常适合您的问题。

鉴于上述类型的尝试通常用于存储与键关联的值,如果您的问题不需要这样做(即您不需要存储输入模式字符串的原始索引并在搜索时返回该索引),有一个密切相关的解决方案可能更适合。正如@JimMischel 在 cmets 中所指出的,Aho–Corasick string matching algorithm 构建了一个类似于 trie 的结构,内部节点之间有额外的链接。如果要匹配的模式集是固定的,并且构建了数据结构,那么对于搜索,它的运行时间与输入长度加上匹配条目的数量成线性关系。

在这个 SO 问题Aho Corasick algorithm 中进行了讨论

您可以在网上找到它的一些实现,例如 C#JavaHaskell

【讨论】:

  • Aho-Corasick 字符串搜索算法构建了一个非常相似的数据结构并且搜索速度非常快。似乎是这个问题的完美解决方案。
  • 是的,这似乎更适合这个特定问题(假设“键”不需要包含关联值)。我将在答案中添加对它的引用。
【解决方案2】:

您可以考虑实现wu-manber,它既易于编码又节省内存。

【讨论】:

    猜你喜欢
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多