我正在尝试使用汉明和Levenshtein距离找到类似的哈希(十六进制哈希)。假设两个哈希值相似,如果它们的汉明距离小于10(不同位的数量)。
Hash 1= ffffff (base 16)
Hash 2= fffff0 (base 16)
两个哈希之间的汉明距离是4.它们是相似的。因为,
Hash 1= 11111111 11111111 11111111 (base 2)
Hash 2= 11111111 11111111 11110000 (base 2)
我有800万个这样的哈希。我想知道什么是适合存储800万哈希的数据结构。我最初尝试“Trie”,但考虑以下情况,
Hash 1 = 0fabde (00001111 10101011 11011110)
Hash 2 = adcbfe (10101010 11001011 11111110)
汉明距离是7.所以我不能做前缀搜索。
我知道我可以使用XOR和Integer.bitCount()来获取不同位的数量,但是我有一个目标哈希和800万个哈希来搜索,即给定哈希我必须找到所有类似的哈希值我们在存储库中有800万个哈希值。
有没有办法有效地存储哈希值,以便减少我的搜索基础?
答案 0 :(得分:2)
如果哈希值与显示的一样小,您可以将它们直接编入索引"直接" - 也就是说,把它们放在一个大数组中,然后对索引做一些数学运算。
仅生成可能对应于请求的汉明距离d
内的哈希值的索引非常简单,只需对包含最多d
集的所有蒙版进行异或位(见下文)。由于有800万个哈希值,但只有1600万个哈希值,因此预计约有一半的访问指数是有用的"即将有一些东西可以找到。
要生成蒙版,您可以使用之前已多次在StackOverflow上发布的旧NextBitPermutation技巧,例如here。对于java,只需使用逻辑右移并将__builtin_ctz
替换为numberOfTrailingZeros
以获取(未测试)
int t = v | (v - 1);
int w = (t + 1) | (((~t & -~t) - 1) >>> (Integer.numberOfTrailingZeros(v) + 1));
此处w
将是v
之后的位排列。
全局结构将类似于(未经测试)
for (int k = 1; k <= d; k++) {
int diff = (1 << k) - 1;
while (diff <= 0xFFFFFF) {
if (hashes[key ^ diff])
// do something with it
diff = nextBitPermutation(diff);
}
}