我刚刚实现了最佳匹配文件搜索算法,以找到与字典中的字符串最接近的匹配项。对代码进行性能分析后,我发现绝大多数时间都花在了计算查询和可能结果之间的距离上。我目前正在使用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)); }
关于Levenshtein距离的Wikipedia条目为优化计算提供了有用的建议- 在您的情况下,最适用的方法是,如果您可以k对最大感兴趣距离(任何超出此范围的值都可以无穷大!)进行限制,则可以减小使计算O(n times k)的,而不是O(n squared)(基本上由只要最小可能距离变得放弃> k)。
k
O(n times k)
O(n squared)
> k
由于您正在寻找最接近的匹配项,因此您可以逐渐减小k到迄今为止找到的最佳匹配项的距离-这不会影响最坏情况的行为(因为匹配项 可能 是按照距离的递减顺序排列,这意味着您我将永远不会纾困),但平均情况应该会有所改善。
我相信,如果您需要获得 显着 更好的性能,则可能必须接受一些强有力的折衷方案,以计算出更近似的距离(从而获得“合理的良好匹配”,而不是最佳的匹配)。