字符串/(字符串向量)匹配的快速算法

时间:2021-01-17 20:16:13

标签: c++ algorithm data-structures hashmap unordered-set

所以我有一个正好有 5 个字符串的 向量 V1。

我有一组向量(称为过滤器)(每个有 5 个字符串)。

我需要一个快速算法,以便我可以查看给定的向量是否与集合中的任何向量匹配。

向量 V1 对集合中的向量进行数学运算(例如 filter1),如果

V1[i] = filter1[i] OR filter[i] = "" (空字符串)

示例:

过滤器:

filter1: "abc" "bcd" "bb" "" ""

filter2:“abc”“bcd”“bb”“ee”“ff”

filter3: "abc" "ddd" "bb" "j" ""

搜索向量:

V1:“abc”、“bcd”、“bb”、“ee”、“ff”

V1 匹配过滤器中的两个向量:filter1filter2

所以我想将过滤器存储在 unordered_set 中。但我不知道如何制作散列函数,因此它可以找到匹配项(它会为不同的向量提供不同的散列值(即使它们可以匹配)。我的另一个想法是构建一个正则表达式。但是再次搜索将是 O(n)。 任何提示如何检查 O(log(n))O(1)(其中 n 是过滤器向量的大小)的匹配?

1 个答案:

答案 0 :(得分:0)

并不完全清楚您想要的所有行为和约束是什么。例如,按照您列出的示例过滤器从左到右的顺序,过滤器是否可以包含“”(您的全部匹配“通配符”),然后是另一个非“”字符串?

无论如何,假设您不允许过滤器具有 "" 通配符后跟非 "" 术语,您可以使用类型创建过滤器的索引...

std::unordered_map<std::string,
  std::variant<filter*,
    std::unordered_map<std::string,
      std::variant<filter*,
        std::unordered_map<std::string,
          std::variant<filter*,
            std::unordered_map<std::string,
              std::variant<filter*,
                std::unordered_map<std::string, filter*>
> > > > > > > > index;

这有效地描述了一个树,其中每个级别可能有一个精确的字符串匹配或一个 "" 通配符过滤器匹配,如果这是最后一个非 {{1 }} 过滤器中的术语,或索引的下一级。

给您筛选的候选对象 filter*,并假设您已经完成了填充索引的明显工作,然后您可以这样搜索:

""

这最多涉及 10 次哈希表查找,因此 O(1) w.r.t.过滤器集大小。

这并不一定意味着它是任何给定数据的最佳性能选择:字符串的典型长度,其中的模式,例如可能以相同的字符开头并且仅在最后一个不同几个字符、过滤器集的长度 - 了解这些可能会建议一种实际上更快的方法。

哈希表的工作效果还取决于所使用的哈希函数。对于较长的字符串,GCC 的字符串哈希函数 - MURMUR32 - 比 Visual C++ 的质量高得多(为了速度,它只包含沿字符串间隔的 10 个字符),并且 GCC 使用主要桶计数,这比 Visual C++ 的功能更不容易发生冲突 - of-2 选择。数据的知识可以建议其他优化,例如如果您知道字符串总是 < 8 个字符,您可以选择将它们放入填充的 uint64_t 并进行直接相等比较,并使用开放寻址/封闭散列哈希表实现来减少 CPU 缓存未命中并提高速度。