找到具有最大公共设置位数的位串对

时间:2012-08-25 13:31:15

标签: algorithm byte bits

我想找到一种算法来查找数组中具有最大公共设置位数的位串(在数组中的所有对中)。我知道可以通过比较数组中的所有位串对来实现这一点,但这是O( n 2 )。有更高效的算法吗?理想情况下,我希望算法通过在每次迭代中处理一个传入的位串来递增地工作。

例如,假设我们有这个位串数组(长度为8):

B1:01010001 
B2:01101010
B3:01101010
B4:11001010
B5:00110001 

这里最好的一对是B2B3,它们有四个常见的设置位。

我发现了一篇似乎描述这种算法的论文(S. Taylor& T. Drummond(2011);“Binary Histogrammed Intensity Patches for Efficient and Robust Matching”; Int.J。Comput.Vis。 94:241-265),但我不理解第252页的描述:

  

这可以在每次迭代中逐步更新,因为需要重新计算的唯一[bitstring]重叠是新的父特征和根中任何其他[bitstrings]的那些,其中“最重叠特征”是所选择的两个中的一个组合。这避免了在每次迭代中需要O(N 2 )重叠比较,并且允许在一秒钟内构建具有700个特征的通常大小的数据库的林。

2 个答案:

答案 0 :(得分:1)

据我所知,Taylor& Drummond(2011)并不打算给出一个O( n )算法,用于在具有最大公共设置位数的数组中查找位串。他们描绘了一个论点,即在将一个新的位串添加到数组之后,可以在O( n )中更新中的最佳对的记录(并删除了两个旧的位串) )。

当然第252页上对算法的解释不是很清楚,我认为他们的草图论证可以在O( n )中更新记录最多是不完整的,所以我可以看到为什么你感到困惑。

无论如何,这是我从文章中解释算法1的最佳尝试。

算法

算法采用位串数组并构造查找树。查找树是二进制林(二进制树集),其叶子是来自阵列的原始位串,其内部节点是新的位串,并且如果节点A是节点B的父节点,则A& B = A(也就是说,A中的所有设置位也在B中设置)。

例如,如果输入是位串的数组:

Array of bitstrings

然后输出是查找树:

Lookup tree

本文所述的算法如下:

  1. R 成为位串的初始集(根集)。

  2. 对于 R 中没有合作伙伴的 R 中的每个bitstring f1 ,找到并记录其合作伙伴 R 中的bitstring f2 - { f1 },它与 f1具有最大的设置位数)并记录它们共有的位数。

  3. 如果 R 中没有任何位串的任何公共设置位,请停止。

  4. f1 f2 R 中具有最大公共设置位数的位串。

  5. p = f1 & f2 f1 f2

  6. R 中删除 f1 f2 ;将 p 添加到 R

  7. 转到第2步。

  8. 分析

    假设数组包含固定长度的 n 位串。然后所描述的算法是O( n 3 ),因为步骤2是O( n 2 ),并且有O( n )迭代,因为在每次迭代中我们从 R 中删除两个位串并添加一个。

    本文包含一个论点,即第2步仅在第一次循环时为Ω( n 2 ),在其他迭代中它为O( n )因为我们只需要找到 p “的伙伴以及 R 中的任何其他位串,其伙伴是被选中的两个中的一个用于组合。”但是,这个论点对我来说并不令人信服:目前尚不清楚只有O(1)其他这样的位串。 (也许有更好的论点?)

    我们可以通过在每对位串之间存储公共设置位的数量,将算法降低到O( n 2 )。这需要O( n 2 )额外的空间。

    参考

    • S上。泰勒& T. Drummond(2011年)。 “用于高效和稳健匹配的二进制直方图强度补丁”。 内部。 J. Comput。 Vis。 94:241-265。

答案 1 :(得分:0)

对于每个位位置,您可以保持两个位置,即那个位置开启和关闭位置的位置。例如,集合可以放在两个二叉树中。

然后你只需要执行set unions,首先是所有8位,而不是7的所有组合,依此类推,直到找到带有两个元素的union。

此处的复杂性在位大小呈指数级增长,但如果它很小且已修复,则这不是问题。

另一种方法可能是将n个k位字符串视为kD空间中的n个点,您的任务是找到最接近的两个点。有很多几何算法可以做到这一点。