寻找一种有效的算法来匹配一组集合中的集合,这些集合由最重叠的成员排序。例如,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));
}
}
看看这是否有帮助......