首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实现模糊搜索建议/词完成

实现模糊搜索建议/词完成
EN

Stack Overflow用户
提问于 2016-07-14 22:00:34
回答 2查看 933关注 0票数 1

我有一串短语的清单。因为这是一个相当长的列表,我也有一个文本框,用户可以键入作为搜索栏。到目前为止,不完全包含在搜索栏中的字母的术语被过滤掉。但是,我想请它列出几个关于这个词可能是什么的建议。

注:,我不是在找“你是说.”或者拼写检查算法,比如这里这里这里 (虽然第一个链接中的这幅图像看起来很好);我希望有一个算法能够建议对一个不完整的单词或短语进行最佳匹配;例如,单词"bat"应该比单词"car"更匹配。

使用Google的方法返回以(大致)相同字母开头最常见的几个字符串也是不切实际的,因为据我所知,列表中的每个元素与其他元素一样常见。

此外,我想在Java (8)中这样做;但是,其他语言答案是可以接受的,只要它们不使用Java没有等效功能的内置函数。如果有用的话,我编写了一个修改版本的Levenshtein距离(下面),它用星号填充搜索字符串,表示“任意字符”。这适用于单个单词,例如"mud""muddy"的完美匹配,但考虑到人们可能使用"car"搜索"race car"时还不够好。

代码语言:javascript
运行
复制
/**
 * <ul>
 * <b><i>searchDistance</i></b><br>
 * <br>
 * <code>&nbsp;public static int searchDistance(String key, String match)</code><br>
 * <br>
 * Gets the Levenshtein distance between <code>key</code> and <code>match</code>. <br>
 * If <code>useAsterisk</code> is true, then the follwing applies: If <code>key</code> is shorter than <code>match</code>, the asterisk <code>'*'</code> is appended to it until the lengths are equal. Asterisks can be used in <code>key</code> to signify 'any character.'
 * @param key - The text to search for
 * @param match - The text to compare <code>key</code> against
 * @param useAsterisk - Whether or not to use asterisks for the purpose described above
 * @return the Levenshtein distance between <code>key</code> and <code>match</code>.
 *         </ul>
 */
public static int searchDistance(String key, String match, boolean useAsterisk) {
    while (key.length() < match.length()) {
        key = key + "*";
    }

    int[][] matrix = new int[key.length() + 1][match.length() + 1];

    for (int i = 0; i < matrix.length; i++) {
        matrix[i][0] = i;
    }

    for (int i = 0; i < matrix[0].length; i++) {
        matrix[0][i] = i;
    }

    for (int a = 1; a < matrix.length; a++) {
        for (int b = 1; b < matrix[0].length; b++) {
            matrix[a][b] = Math.min(Math.min(matrix[a - 1][b] + 1, matrix[a][b - 1] + 1), matrix[a - 1][b - 1] + (key.charAt(a - 1) == match.charAt(b - 1) || key.charAt(a - 1) == '*' ? 0 : 1));
        }
    }

    return matrix[matrix.length - 1][matrix[0].length - 1];
}

TL;DR:有什么好的方法可以为搜索词提供完成建议吗?

提前感谢!

EN

回答 2

Stack Overflow用户

发布于 2016-07-15 14:38:06

尝试查看,K Shingles方法在:http://infolab.stanford.edu/~ullman/mmds/book.pdf:第77页

这可能会为推进这种模糊搜索系统提供一些思路。

票数 1
EN

Stack Overflow用户

发布于 2016-07-15 17:01:02

总有一种简单的,蛮力的方法。即使有一组相当大的短语,它也能很好地工作。

想象一下,你有一个100万个短语的列表。用户输入字母“c”。搜索包含字母“c”的所有短语列表,并显示它们。你也保留着这个结果。

然后用户键入'a‘。现在,在上一次搜索返回的字符串列表中搜索字符串"ca“。所以你已经把搜索范围从所有短语减少到你知道的包含字母'c‘的那些短语。考虑到大约37%的英语单词包含字母“c”(见http://phrontistery.info/ihlstats.html),你已经把你的单子减少了近三分之二。

无论如何,你现在有一个包含字母"ca“的短语列表。与所有短语的列表相比,这个列表将相当小。您可以在用户键入字符时继续细化列表。

如果对整个列表的初始搜索时间过长,您可以轻松地通过创建字典、按字母编制索引和拥有包含该字母的单词列表来优化该列表。例如,“c”的条目将包含“赛车”、“汽车”、“猫”、“主雕刻家”等,因此不需要搜索来获得初始列表。

使用字典方法的另一个好处是,您可以对每个字母的列表进行预处理,以便以字母开头的单词位于列表的前面。这很好,因为大多数情况下,当某人在搜索时,他会寻找一个以他输入的第一个字母开头的单词或短语。但你可以很容易地根据受欢迎程度或任何其他标准来安排。

我曾多次使用这种方法,而且效果很好。它的实现非常简单,而且执行速度通常足够快,而不需要任何优化。我前面提到的字典优化对于简单的蛮力方法不起作用的少数情况是足够的,有一次我需要两本字典:一个用于第一个字符,另一个用于字母对。

即使这不是最终的解决方案,拥有它也是有用的,因为它很容易被证明是正确的,并且很容易测试其他更复杂的算法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38384947

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档