我在数据库表中有大约一千万个文件的spamsum复合哈希值,我想找到彼此相似的文件。 Spamsum哈希由两个最大64字节的CTPH哈希组成,它们看起来像这样:
384:w2mhnFnJF47jDnunEk3SlbJJ+SGfOypAYJwsn3gdqymefD4kkAGxqCfOTPi0ND:wemfOGxqCfOTPi0ND
它们可以分为三个部分(在冒号上分割字符串):
384
w2mhnFnJF47jDnunEk3SlbJJ+SGfOypAYJwsn3gdqymefD4kkAGxqCfOTPi0ND
wemfOGxqCfOTPi0ND
块大小是指第一个签名的块大小,第二个签名的块大小是第一个签名的块大小(此处:384 x 2 = 768)。每个文件都有这些复合哈希中的一个,这意味着每个文件都有两个具有不同块大小的签名。
只有在块大小对应的情况下才能比较spamsum签名。也就是说,上面的复合哈希可以与包含块大小为384或768的签名的任何其他复合哈希进行比较。具有相似块大小的哈希的签名字符串的相似性可以作为两者之间相似性的度量。哈希表示的文件。
所以如果我们有:
file1.blk2 = 768
file1.sig2 = wemfOGxqCfOTPi0ND
file2.blk1 = 768
file2.sig1 = LsmfOGxqCfOTPi0ND
通过计算两个签名的一些加权编辑距离(如Levenshtein距离),我们可以了解两个文件的相似程度。这两个文件看起来非常相似。
leven_dist(file1.sig2, file2.sig1) = 2
还可以计算两个哈希值之间的归一化相似度得分(详见here)。
我想根据这些哈希找到任何两个超过70%相似的文件,我非常喜欢使用可用的软件包(或API / SDK),尽管我不怕编码我的解决问题的方法。
我已经尝试打破哈希并使用Lucene(4.7.0)索引它们,但搜索似乎是缓慢而乏味的。以下是我尝试过的Lucene查询的示例(对于每个单一签名 - 每个哈希两次并使用区分大小写的KeywordAnalyzer):
(blk1:768 AND sig1:wemfOGxqCfOTPi0ND~0.7) OR (blk2:768 AND sig2:wemfOGxqCfOTPi0ND~0.7)
似乎Lucene的incredibly fast Levenshtein automata不接受超过2的编辑距离限制(我需要它支持高达0.7 x64≃19)并且其正常编辑距离算法未针对长搜索术语进行优化({ {3}}。)那就是说,我的查询可能没有针对我想做的事情进行优化,所以请不要犹豫,纠正我。
我想知道我是否可以使用Lucene提供的任何算法来完成我所需要的,而不是直接计算编辑距离。我听说BK树是索引此类搜索的最佳方式,但我不知道算法的可用实现(Lucene是否使用了这些?)。我也听说过一个可能的解决方案是使用n-gram方法缩小搜索列表的范围,但我不确定如何在包容性和速度方面编辑距离计算(我很确定Lucene支持那个)。顺便说一句,有没有办法让Lucene在并行模式下运行术语搜索?
鉴于我使用Lucene仅预先匹配哈希并且我稍后使用适当的算法计算真实的相似性得分,我只需要一种至少与相似性得分计算中使用的Levenshtein距离一样包容的方法 - - 也就是说,我不希望预匹配方法排除由评分算法标记为匹配的哈希值。
感谢任何帮助/理论/参考/代码或线索。
答案 0 :(得分:3)
这不是问题的明确答案,但从那以后我尝试了很多方法。我假设哈希值保存在数据库中,但这些建议对于内存数据结构仍然有效。
上述步骤进行了良好的预匹配,并且大大减少了每个签名必须与之进行比较的签名数量。只有在这些之后才能计算出改进的Levenshtein / Damreau距离。