C++ 基于多分量密钥的快速局部匹配

C++ 基于多分量密钥的快速局部匹配,c++,algorithm,data-structures,stl,C++,Algorithm,Data Structures,Stl,我有一个由 定义了比较运算符的poi数据类型: typedef boost::tuple<int, char, unsigned long> Key; 我想比O(N)更快地执行匹配 N是图案的数量 我从模式的自定义比较运算符1开始 将它们存储在排序向量中。运算符1只是排序 星号排在其他的后面。然后执行查询 使用std::lower_与自定义比较运算符2绑定。 运算符2在比较期间忽略未设置的关键组件。 但我想我无法摆脱单一排序向量 因为如果第二个分量是*而我省略了它,那么 不保证对第

我有一个由 定义了比较运算符的poi数据类型:

typedef boost::tuple<int, char, unsigned long> Key;
我想比O(N)更快地执行匹配 N是图案的数量

我从模式的自定义比较运算符1开始 将它们存储在排序向量中。运算符1只是排序 星号排在其他的后面。然后执行查询 使用std::lower_与自定义比较运算符2绑定。 运算符2在比较期间忽略未设置的关键组件。 但我想我无法摆脱单一排序向量 因为如果第二个分量是*而我省略了它,那么 不保证对第三个组件的“切片”进行排序
通过std::lower_bound,我得到了一些有用的东西。

按某种顺序对键进行排序。为每个组件建立索引,保持相同的排序顺序

使用索引查找每个组件的下一项。如果索引指向同一项,则有一个匹配项。如果没有,则选择指向最小项的组件(按排序顺序),并跳过,直到至少达到最大项为止(std::lower_bound会这样做)

这与相交排序列表的算法相同


速度取决于数据的密度。如果您搜索(*,*,true)和95%的数据匹配,您将是O(N)。如果数据足够稀疏,这可能会非常快。

您需要为每个搜索“形状”创建一个索引。建立索引的成本很高,但您可以使用无序的_映射来获得搜索的平均恒定时间。最好为每个索引使用多个键,并尝试对它们进行组织,以便这些有序键列表的所有前缀集覆盖尽可能多(无序)的键集。例如,假设有4个字段,A、B、C和D,那么您可以创建4个索引:ABCD、BCD、CDA、DBA。现在,任何指定全部4个字段或4个字段中的任意3个字段的查询都可以用一个二进制搜索来回答,并且唯一需要您描述的连接类型的查询是那些只指定AC或只指定AD的查询(当然,您可以再添加两个索引来处理这个问题)。我一次根据一组模式匹配一个键。比如说,我有K(1,2,3)和[P(1,2,4),P(1,2,*)]。我应该使用什么复合索引?正如索林所提到的,我应该为每个组件建立索引,查询每个索引中的组件值和*并将结果(六个)列表相交。@j_random_hacker你是对的,但我更愿意把它作为一种优化。性能取决于您在相交列表中的跳转速度,这取决于条目之间的差异。如果制作复合键,则会显著增加这些字段的熵(速度更快),但也会占用更多空间(特别是如果尝试覆盖不同的字段组合)。除非你基准测试并注意到你需要更快,否则我不会费心去做。@Sorin:我很困惑;如果将索引表示为指向原始数据记录(即,其中的整数位置)的指针数组,则任意数量的键上的索引占用的空间量相同。当然,在k个键上建立索引需要(最多)k倍于在1个键上建立索引的时间,但您只需要做一次。另外,我不确定你这里所说的“熵”是什么意思。对于n个指定的字段,你的算法所用的时间与每个字段的匹配并集大小的n倍成正比,再加上n个二进制搜索。如果你有合适的n键索引,我的索引需要的时间与交叉点的大小成比例,再加上一个二进制搜索。如果没有针对所有n个键的单个索引,但是有itypedef boost::tuple< boost::optional<int> , boost::optional<char> , boost::optional<unsigned long> > Pattern;
Key(1, 2, 3) match Pattern(1, 2, *)
Key(1, 2, 3) match Pattern(*, 2, 3)