Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 联系人数据库中快速子串搜索算法_Java_Algorithm_Lucene_Full Text Search_Search Engine - Fatal编程技术网

Java 联系人数据库中快速子串搜索算法

Java 联系人数据库中快速子串搜索算法,java,algorithm,lucene,full-text-search,search-engine,Java,Algorithm,Lucene,Full Text Search,Search Engine,我有一个数据库,大约有一百万个名字和地址。该数据库应该公开,以便在网页上进行“谷歌建议”式的即时搜索。我正在寻找一个有效的算法/数据结构,它可以帮助我实现这一点 这比仅仅使用a或a更困难的是,它必须支持省略某些名称的查询。例如,当用户键入“Elvis Pr”时,应建议输入“Elvis Aaron Presley” 我希望在内存中获得整个索引(我有大约4GB的RAM用于此) 该应用程序是用Java编写的,因此指向基于Java的库的链接被认为非常有用。我一直在研究和,但我还没有弄清楚我可以使用哪种类

我有一个数据库,大约有一百万个名字和地址。该数据库应该公开,以便在网页上进行“谷歌建议”式的即时搜索。我正在寻找一个有效的算法/数据结构,它可以帮助我实现这一点

这比仅仅使用a或a更困难的是,它必须支持省略某些名称的查询。例如,当用户键入“Elvis Pr”时,应建议输入“Elvis Aaron Presley”

我希望在内存中获得整个索引(我有大约4GB的RAM用于此)

该应用程序是用Java编写的,因此指向基于Java的库的链接被认为非常有用。我一直在研究和,但我还没有弄清楚我可以使用哪种类型的索引来解决我的问题

您可以尝试使用带有字符串距离度量的,如参见

编辑: 发明一个距离度量是困难的,但我碰巧知道一个你可以使用的,叫做,基于信息差异的距离度量。其工作原理如下:

取两个字符串x=“Elvis Pr”和y=“Elvis Aaron Presley”

对于每一项,计算出单图和双图的多集:

x = {e, l, v, i, s, _, p, r, el, lv, vi, is, s_,  _p, pr}
y = {ex3, lx2, v, i, sx2, _x2, ax2, rx2, o, n, p, y, el, lv, vi, is, s_, _a, aa, ar, ro, on, n_, _p, pr, re, es, sl, le, ey}
现在来看看这两个术语

{e, l, v, i, s, _, p, r, el, lv, vi, is, s_, _p, pr}
计算乘积
(f_x(t)/(f_x(t)+f_y(t))^{f_x(t)/2}*(f_y(t)/(f_x(t)+f_y(t))^{f_y(t)/2}
所以

把所有这些加起来,你应该得到一个[0.5,1]范围内的数字,这样你就可以通过乘以2减去1,更有效地将其缩放到[0,1]范围


但是,这不是一个离散的距离度量,因此您必须使用另一个度量索引,例如

,可能您实际需要的是一个搜索,其中用户键入的每个单词必须显示为联系人中某个单词的前缀。这比一般的子字符串搜索更简单、更快

  • 构建属于任何联系人的所有单词的单个排序数组,并在每个单词旁边存储一个“联系人ID”字段(例如[Aaron/1、Aleksander/2、Blomskøld/2、Elvis/1、Presley/1])
  • 对于用户键入的每个单词,分别使用二进制搜索查找以该单词开头的名称范围(这必须是数组中连续的索引范围)。由于用户通常在每次击键时只调整一个单词,因此每次击键时只需重新计算其中一个范围——事实上,在通常情况下键入额外字母时,甚至可以更有效地执行此重新计算步骤,因为这只会缩小匹配单词的范围
  • 最后,将联系人ID集相交以生成可能性列表。要显示这些可能性,您需要第二个数组,它由联系人ID索引并包含全名

  • Solr提供了一个全功能的自动建议功能OOTB。提供从流行查询生成的一些背景信息。但是你可以很容易地调整它来构建一些先验知识,比如你描述的场景。

    看看,看起来你有一个非常相似的用例。他们使用Bloom过滤器来搜索前缀,并使用前向索引来消除误报

    谢谢,我来看看bk树。我想我需要做一个不同于普通levenshtein的距离度量,例如在搜索中缺少一个(可能很长的)中间名应该返回一个较低的距离。我知道另一个度量,我编辑了我的答案来描述它。Cleo正是我想要的。谢谢如果添加了一个新联系人,删除了一个联系人怎么办?我需要使用阵列吗@Doggynub:您不需要使用它——您可以在O(n)时间内删除元素,或者找到插入元素的正确位置,然后将其插入O(n)。不可否认,这仍然相当缓慢,因此最好保持一个单独的添加和删除排序列表,并在其足够大时将其与主列表合并。
    e  = ((1/15) / (1/15 + 3/37))^(1/30) * ((3/37) / (1/15 + 3/37))^(3/74)
    l  = ((1/15) / (1/15 + 2/37))^(1/30) * ((2/37) / (1/15 + 2/37))^(2/74)
    v  = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)
    i  = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)
    s  = ((1/15) / (1/15 + 2/37))^(1/30) * ((2/37) / (1/15 + 2/37))^(2/74)
    _  = ((1/15) / (1/15 + 2/37))^(1/30) * ((2/37) / (1/15 + 2/37))^(2/74)
    p  = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)
    r  = ((1/15) / (1/15 + 2/37))^(1/30) * ((2/37) / (1/15 + 2/37))^(2/74)
    el = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)
    lv = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)
    vi = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)
    is = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)
    s_ = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)
    _p = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)
    pr = ((1/15) / (1/15 + 1/37))^(1/30) * ((1/37) / (1/15 + 1/37))^(1/74)