一尘不染

计算Levenshtein距离的最有效方法

algorithm

我刚刚实现了最佳匹配文件搜索算法,以找到与字典中的字符串最接近的匹配项。对代码进行性能分析后,我发现绝大多数时间都花在了计算查询和可能结果之间的距离上。我目前正在使用2-D数组实现该算法来计算Levenshtein距离,这使该实现成为O(n
^ 2)运算。我希望有人可以提出一种更快的方法来做同样的事情。

这是我的实现:

public int calculate(String root, String query)
{
  int arr[][] = new int[root.length() + 2][query.length() + 2];

  for (int i = 2; i < root.length() + 2; i++)
  {
    arr[i][0] = (int) root.charAt(i - 2);
    arr[i][1] = (i - 1);
  }

  for (int i = 2; i < query.length() + 2; i++)
  {
    arr[0][i] = (int) query.charAt(i - 2);
    arr[1][i] = (i - 1);
  }

  for (int i = 2; i < root.length() + 2; i++)
  {
    for (int j = 2; j < query.length() + 2; j++)
    {
      int diff = 0;
      if (arr[0][j] != arr[i][0])
      {
        diff = 1;
      }
      arr[i][j] = min((arr[i - 1][j] + 1), (arr[i][j - 1] + 1), (arr[i - 1][j - 1] + diff));
    }
  }
  return arr[root.length() + 1][query.length() + 1];
}

public int min(int n1, int n2, int n3)
{
  return (int) Math.min(n1, Math.min(n2, n3));
}

阅读 210

收藏
2020-07-28

共1个答案

一尘不染

关于Levenshtein距离的Wikipedia条目为优化计算提供了有用的建议-
在您的情况下,最适用的方法是,如果您可以k对最大感兴趣距离(任何超出此范围的值都可以无穷大!)进行限制,则可以减小使计算O(n times k)的,而不是O(n squared)(基本上由只要最小可能距离变得放弃> k)。

由于您正在寻找最接近的匹配项,因此您可以逐渐减小k到迄今为止找到的最佳匹配项的距离-这不会影响最坏情况的行为(因为匹配项 可能
是按照距离的递减顺序排列,这意味着您我将永远不会纾困),但平均情况应该会有所改善。

我相信,如果您需要获得 显着 更好的性能,则可能必须接受一些强有力的折衷方案,以计算出更近似的距离(从而获得“合理的良好匹配”,而不是最佳的匹配)。

2020-07-28