用于快速确定两个比特序列之间的相似性的包

时间:2010-02-13 11:36:47

标签: comparison packages bit-manipulation performance

我需要将查询位序列与高达一百万位序列的数据库进行比较。所有位序列都是100位长。我需要尽可能快地查找。是否有任何包可以快速确定两个比特序列之间的相似性? --Edit--位序列是位置敏感的。

我见过possible algorithm on Bit Twiddling Hacks但是如果有一个现成的包会更好。

3 个答案:

答案 0 :(得分:2)

如果数据库是静态的,您可能希望在其上构建树数据结构。

以递归方式或多个线程搜索树,每次搜索保留实际的差异变量。如果实际差异大于您认为的“相似”,则中止搜索。

E.g。假设我们有以下树:

      root
   0       1
 0   1   0   1
0 1 0 1 0 1 0 1

如果你想寻找类似于011的模式,并且只希望最多允许1个不同的位,那就像这样搜索(递归或多线程):

  • 从根
  • 开始
  • 取左分支(0),这是相似的,所以差异仍为0
    • 取左分支(0),这是不同的,所以差异变为1,这仍然是可以接受的
      • 取左分支(0),这是不同的,所以差异变为2,这太高了。 Abort看着这个分支。
      • 取右分支(1),这是相等的,所以差异保持为1,继续在此分支中搜索(此处未显示)
    • 取右分支(1),这是相等的,所以差异保持为0,继续
      • 取左分支(0),这是不同的,所以差异变为1,这仍然可以接受,继续。

这一直持续到你找到了你的位模式。

如果您的位模式更具动态性并在应用程序中进行更新,则必须更新树。

如果内存有问题,请考虑转到64位。

答案 1 :(得分:2)

如果你想查找50个大多数匹配模式,我们可以假设输入数据集是静态的(或者可以动态更新),你可以重复上一个注释的初始阶段,这样:

  • 对于每个位模式,计算位数。
  • 将位模式存储在multi_map中(如果使用STL,Java可能有类似的东西)

然后,使用以下算法:

  • 制作2个集合:一个用于存储找到的模式,一个用于存储可能的好模式(第二个集合应该是地图,将'距离'映射到模式)
  • 采用自己的模式并计算位数,假设这是N
  • 在索引N的多图中查看,所有这些模式将具有相同的总和,但不一定完全相同
  • 比较索引N处的所有模式。如果它们相等,则将结果存储在第一个集合中。如果它们不相等,则将结果存储在第二个集合/映射中,使用差值作为键。
  • 在索引N-1的多图中查看,所有这些模式的距离均为1或更多
  • 比较索引N-1处的所有模式。如果它们的距离为1,则将它们存储在第一个集合中。如果距离较大,请将结果存储在第二个集合/地图中,并使用差值作为键。
  • 重复索引N + 1
  • 现在查看第二个集合/地图,查看是否存在距离1的内容。如果是,请从第二个集合/地图中删除它们并将它们存储在第一个集合中。

对距离2,距离3,......重复此操作,直到你有足够的模式。

如果所需图案的数量不是太大,而且平均距离也不是太大,那么图案之间的实际比较数可能只有几个百分点。

不幸的是,由于模式将使用高斯曲线分布,因此仍需要检查相当多的模式。我没有对它进行数学检查,但在实践中,如果你不想要数百万的太多模式,并且平均距离不是太远,你应该能够找到最接近的一组通过只检查总位模式的几个百分点来确定模式。

请让我及时了解您的结果。

答案 2 :(得分:1)

我提出了第二种选择。

对于百万个的每个位模式计数位数并将位模式存储在STL multi_map中(如果您使用C ++编写)。

然后计算模式中的位数。假设您在位模式中设置了N位。

如果您现在想要允许最多D差异,请查找具有ND,N-D + 1,...,N-1,N,N + 1,... N的multi_map中的所有位模式+ D-1,N + D位。

不幸的是,multi_map中位模式的划分将遵循高斯模式,这意味着在实践中你仍然需要比较一些位模式。

(最初我认为这可以通过计算偶数0和不均匀的1来解决,但事实并非如此。)

假设您想要允许1个差异,您必须在100个可能的插槽中查找multi_map中的3个插槽,留下3%的实际位模式进行完全比较。