【问题标题】:Optimizing a simple search algorithm优化一个简单的搜索算法
【发布时间】:2010-10-26 03:20:50
【问题描述】:

我一直在玩弄一个相当简单的自制搜索引擎,现在我正在玩弄一些相关性排序代码。

它不是很漂亮,但在聪明的算法方面我不是很好,所以我希望我能得到一些建议:)

基本上,我希望每个搜索结果都根据匹配搜索条件的单词数获得评分。每个完全匹配的单词得 3 分,部分匹配得 1 分

例如,如果我搜索“冬雪”,结果如下:

  • 冬天 => 6分
  • 冬天 下雪ing => 4 分
  • 冬天土地 => 4分
  • 冬天 太阳 => 3 分
  • 冬天土地下雪ing => 2 分

代码如下:

String[] resultWords = result.split(" ");
String[] searchWords = searchStr.split(" ");
int score = 0;
for (String resultWord : resultWords) {
    for (String searchWord : searchWords) {
        if (resultWord.equalsIgnoreCase(searchWord))
            score += 3;
        else if (resultWord.toLowerCase().contains(searchWord.toLowerCase()))
            score++;
    }
}

【问题讨论】:

  • 您要解决的具体问题是什么?是不是太慢了?使用大量内存?你想到了什么优化?
  • 速度主要是。事实证明,这可能是数据库的瓶颈。

标签: java optimization search


【解决方案1】:

您的代码对我来说似乎没问题。我建议做些小改动:

由于您正在经历所有可能的组合,因此您可能会在一开始就得到您背部的toLowerCase()

此外,如果已经发生完全匹配,则无需执行另一个 equals

    result = result.toLowerCase();
    searchStr = searchStr.toLowerCase();

    String[] resultWords = result.split(" ");
    String[] searchWords = searchStr.split(" ");
    int score = 0;
    for (String resultWord : resultWords) {
        boolean exactMatch = false;
        for (String searchWord : searchWords) {
            if (!exactMatch && resultWord.equals(searchWord)) {
                exactMatch = true;
                score += 3;
            } else if (resultWord.contains(searchWord))
                score++;
        }
    }

当然,这是一个非常基础的级别。如果您真的对计算机科学这一领域感兴趣并想了解更多有关实施搜索引擎的信息,请从以下术语开始:

【讨论】:

  • 我迟到了:(。唯一的区别是我将它命名为exactMatchFound。+1
【解决方案2】:
  • stemming
  • 对于首字母缩写词,区分大小写很重要,即SUN;任何同时匹配内容和大小写的单词的权重都必须超过 3 分(5 或 7)?
  • 使用strategy design pattern

例如,考虑这个简单的分数模型:

interface ScoreModel {
     int startingScore();
     int partialMatch();
     int exactMatch();
}

...

int search(String result, String searchStr, ScoreModel model) {
    String[] resultWords = result.split(" ");
    String[] searchWords = searchStr.split(" ");
    int score = model.startingScore();

    for (String resultWord : resultWords) {
        for (String searchWord : searchWords) {
            if (resultWord.equalsIgnoreCase(searchWord)) {
                score += model.exactMatch();
            } else if (resultWord.toLowerCase().contains(searchWord.toLowerCase())) {
                score += model.partialMatch();
            }
        }
    }

    return score;
}

【讨论】:

    【解决方案3】:

    可以通过预处理数据库来完成基本优化:不要每次都将条目拆分为单词。

    在将每个条目添加到数据库期间为每个条目构建单词列表(首选哈希或二叉树以加速列表中的搜索),删除所有太短的单词,小写并存储此数据以供进一步使用。

    在搜索开始时对搜索字符串执行相同的操作(拆分、小写、清除),并使用此单词列表与每个条目单词列表进行比较。

    【讨论】:

    • 更高级的优化可以通过过滤单词形式(去除常见的结尾)、构建一个全局哈希 [word => db entry] 并将其用于早期条目过滤来完成。例如 - 仅将在全局哈希中至少有一个匹配项与搜索字符串单词之一进行比较。
    【解决方案4】:

    1) 您可以先对 searchWords 进行排序。一旦结果词按字母顺序排列在当前搜索词之后,您就可以跳出循环。

    2) 更好的是,对两者进行排序,然后同时沿着两个列表查找匹配项。

    【讨论】:

      【解决方案5】:

      您可以使用正则表达式来查找匹配模式的模式和长度(用于后面的分类/评分)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-17
        • 1970-01-01
        • 1970-01-01
        • 2019-10-17
        • 2016-12-05
        • 1970-01-01
        • 2015-12-05
        • 1970-01-01
        相关资源
        最近更新 更多