快速汉明距离得分

时间:2010-06-22 23:33:13

标签: sorting pattern-matching hamming-distance

有一个包含N个固定长度字符串的数据库。 有一个相同长度的查询字符串。 问题是从数据库中获取具有最小汉明距离的前k个字符串到q。

N很小(约400),弦长,长度固定。数据库不会更改,因此我们可以预先计算索引。查询变化很大,缓存和/或预计算不是一种选择。每秒有很多。我们总是需要k结果,即使k-1结果匹配0(在汉明距离上排序并取第一个k,因此局部敏感散列和类似方法不会这样做)。 kd-tree和类似的空间分区可能比线性搜索表现更差(字符串可能很长)。 BK树目前是最佳选择,但它仍然比它需要的慢和复杂。

感觉就像有一个算法,它将建立一个索引,它将在很少的步骤中丢弃大多数条目,留下k <= t&lt;&lt;用于计算实际汉明距离的N个条目。

人们建议基于Levenstein距离的模糊字符串匹配 - 谢谢,但问题要简单得多。基于广义距离度量的方法(如BK树)是好的,但也许有一些利用上述事实(小DB /长固定大小的字符串,简单的汉明距离)

链接,关键字,论文,想法? =)

4 个答案:

答案 0 :(得分:11)

这似乎是一个Vantage Point (VP tree)可能有效的任务......因为汉明距离应该满足三角不等式定理,你应该能够应用它......它也有利于识别最近的k。我在图像索引数据库设置中已经看过了......你可以查看this paper的第5部分作为我所谈论的一个例子(虽然在不同的领域)。

答案 1 :(得分:4)

所有汉明距离都可以使用下面的python代码在O(K ^ 2 / D)中生成 在某些情况下,这比O(N * K)的普通代码更快。

其中N是固定长度字符串的数量
K是每个弦的长度
和D是字典的大小。

# DATABASE is a tuple of the strings
# eg. ('asdfjjajwi...', 'hsjsiei...', ...)

# SINGLE is the string you are matching
# eg. 'jfjdkaks...'

SIZE_OF_STRING = 5000
NUMBER_OF_STRINGS = 400
FIRST_K_REQUIRED = 100

def setup_index():
  index = []
  for x in xrange(SIZE_OF_STRING):
    index_dict = {}
    for y in xrange(NUMBER_OF_STRINGS):
      temp = index_dict.get(DATABASE[y][x], [])
      temp.append(y)
      index_dict[DATABASE[y][x]] = temp
    index.append(index_dict)
  return index

index = setup_index()

output = []
for x in xrange(NUMBER_OF_STRINGS):
  output.append([SIZE_OF_STRING, x])

for key, c in enumerate(SINGLE):
  for x in index[key][c]:
    output[x][0] -= 1

output.sort()
print output[:FIRST_K_REQUIRED]

仅当SIZE_OF_STRING / DICTIONARY_SIZE&lt;时,这是一种更快的方法。 NUMBER_OF_STRINGS。

希望这有帮助。


编辑: 上述代码的复杂性不正确。

汉明距离平均可以用O(N * K / D)产生 在 ALL 情况下,这比O(N * K)的普通代码更快。

其中N是固定长度字符串的数量
K是每个弦的长度
和D是字典的大小。

答案 2 :(得分:1)

根据我的理解,BK树非常适合查找与查询字符串最多K“差异”的所有字符串。这是一个与查找X最接近元素不同的问题。这可能是性能问题的原因。

我的第一个倾向是,如果速度非常重要,那么最终目标应该是构建一个deterministic finite automaton(DFA)来处理这个问题。 Donald Knuth处理了一个相关问题并开发了一种名为Trie的方法来模拟DFA。当您在起始字典中有许多可能的单词进行搜索时,此方法特别好。我认为你的问题可能是这项工作的有趣延伸。在他的原创作品中,DFA的目标是尝试将输入字符串与字典中的单词进行匹配。我相信对于这个问题可以做同样的事情,而是将最近的K项返回给查询。实质上,我们正在扩大接受国的定义。

这是否切实可行取决于需要包含的接受状态的数量。我认为关键的想法是兼容的集合。例如,想象一下在数字行上我们有元素1,2,3,4,5并且对于任何查询都想要两个最接近的元素。元素2可以是两个可能的集合(1,2)或(2,3),但是2永远不能是4或5的集合。它已经晚了所以我不确定构建DFA的最佳方法时刻。似乎答案中可能有一篇不错的论文。

答案 3 :(得分:0)

这个问题确实与Knuth&#34; trie&#34;算法中有几个非常优化的特殊解决方案 - 主要与它们的高速缓存一致性和CPU指令辅助加速(按位特征)有关。

对于相关问题而言,trie是一个很好的解决方案 - 字符串开头的相似性,这当然使其成为从字符串原点开始的任何点找到最低限度唯一字符串解决方案集的完美解决方案。在这种情况下,按位trie在实践中具有平均性能O(1),最坏情况O(m)其中M是密钥长度。总的来说,它的搜索,插入和删除性能与哈希相同,只是它没有纯哈希数组的冲突问题。

我碰到了这个问题,因为我正在寻找有关按位尝试的信息,并意识到它们与某些汉明算法的相似性,所以这类算法可能对你来说是一个富有成效的研究领域。祝你好运。