用重叠成员匹配集合的算法

时间:2014-03-13 13:18:40

标签: algorithm set match

寻找一种有效的算法来匹配一组集合中的集合,这些集合由最重叠的成员排序。例如,2个相同的集合是最佳匹配,而没有重叠成员是最差的。

因此,算法会输入一组集合,并返回由具有最多重叠成员的集合排序的匹配集对。

对有效实现这一目标的想法感兴趣。蛮力方法是尝试所有组合和排序,当集合的数量非常大时,这显然不是非常高效。

编辑:用例 - 假设已存在大量集合。当新集到达时,运行算法并且输出包括匹配集(具有至少一个元素重叠),按最匹配到最少排序(无论新/输入集中有多少项)。希望澄清我的问题。

2 个答案:

答案 0 :(得分:0)

如果您能够提供可能出错的近似算法,那么您应该考虑MinHash

该算法允许在恒定时间内估计2组之间的相似性。对于任何构造的集合,计算固定大小的签名,然后在估计相似性时仅比较签名。使用的相似性度量是Jaccard distance,其范围从0(不相交集)到1(相同集)。它被定义为两个给定集合的交集比。

使用这种方法,任何新的集合都必须与所有现有的集合进行比较(在线性时间内),然后结果可以合并到顶部列表中(您可以使用有界搜索树/堆来实现此目的)。

答案 1 :(得分:0)

由于可能的不同值的数量不是很大,如果只是在"大整数"中设置第n位,则可以得到相当有效的散列。当第n个数字出现在你的集合中时。然后,您可以使用简单的按位AND查找集合之间的重叠,然后是"计数设置位"操作。在64位架构上,这意味着您可以在大约16个周期中查找两个数字(1000个可能值中)之间的相似性,而不管每个群集中的值的数量。随着集群变得越来越稀疏,这将成为一种效率较低的算法。

仍然 - 我实现了我在这里附加的一些代码中可能需要的一些基本功能 - 没有记录,但我认为合理可理解。在这个例子中,我将数字设置得很小,所以我可以手动检查结果 - 你可能想要改变一些#defines来获得更大的值范围,显然你会想要一些动态列表等来跟上不断增长的目录

#include <stdio.h>
// biggest number you will come across: want this to be much bigger
#define MAXINT 25
// use the biggest type you have - not int
#define BITSPER (8*sizeof(int))
#define NWORDS (MAXINT/BITSPER + 1)
// max number in a cluster
#define CSIZE 5

typedef struct{
  unsigned int num[NWORDS]; // want to use longest type but not for demo
  int newmatch;
  int rank;
} hmap;

// convert number to binary sequence:
void hashIt(int* t, int n, hmap* h) {
  int ii;
  for(ii=0;ii<n;ii++) {
    int a, b;
    a = t[ii]%BITSPER;
    b = t[ii]/BITSPER;
    h->num[b]|=1<<a;
  }
}

// print binary number:
void printBinary(int n) {
  unsigned int jj;
   jj = 1<<31;
   while(jj!=0) {
     printf("%c",((n&jj)!=0)?'1':'0');
     jj>>=1;
   }
   printf(" ");
}

// print the array of binary numbers:
void printHash(hmap* h) {
  unsigned int ii, jj;
  for(ii=0; ii<NWORDS; ii++) {
   jj = 1<<31;
   printf("0x%08x: ", h->num[ii]);
   printBinary(h->num[ii]);
  }
  //printf("\n");
}

// find the maximum overlap for set m of n
int maxOverlap(hmap* h, int m, int n) {
  int ii, jj;
  int overlap, maxOverlap = -1;
  for(ii = 0; ii<n; ii++) {
    if(ii == m) continue; // don't compare with yourself
    else {
      overlap = 0;
      for(jj = 0; jj< NWORDS; jj++) {
        // just to see what's going on: take these print statements out
        printBinary(h->num[ii]);
        printBinary(h->num[m]);
        int bc = countBits(h->num[ii] & h->num[m]);
        printBinary(h->num[ii] & h->num[m]);
        printf("%d bits overlap\n", bc);
        overlap += bc;
      }
      if(overlap > maxOverlap) maxOverlap = overlap;
    }
  }
  return maxOverlap;
}


int countBits (unsigned int b) {
  int count;

  for (count = 0; b != 0; count++) {
    b &= b - 1; // this clears the LSB-most set bit
  }
  return count;
}

int main(void) {
 int cluster[20][CSIZE];
 int temp[CSIZE];
 int ii,jj;
 static hmap H[20]; // make them all 0 initially
 for(jj=0; jj<20; jj++){
  for(ii=0; ii<CSIZE; ii++) {
   temp[ii] = rand()%MAXINT;
  }
  hashIt(temp, CSIZE, &H[jj]);
 }
 for(ii=0;ii<20;ii++) {
  printHash(&H[ii]);
  printf("max overlap: %d\n", maxOverlap(H, ii, 20));
 }
}

看看这是否有帮助......