Improved the LevenshteinDistance class

This commit is contained in:
Jaime Martinez Rincon 2017-01-14 01:20:14 +01:00
parent d5741c16a2
commit 1e4f0df968

View File

@ -1,87 +1,59 @@
package me.jaimemartz.lobbybalancer.utils; package me.jaimemartz.lobbybalancer.utils;
public class LevenshteinDistance { public class LevenshteinDistance {
public static String getClosestString(String input, String[] options) { public static <T> T closest(Iterable<T> collection, T target) {
int lowestDistance = 10; int distance = Integer.MAX_VALUE;
String lowest = ""; T closest = null;
for (String string : options) { for (T object : collection) {
int distance = getLevenshteinDistance(input, string); int current = distance(object.toString(), target.toString());
if (distance < lowestDistance) { if (current < distance) {
lowestDistance = distance; distance = current;
lowest = string; closest = object;
} }
} }
return lowest; return closest;
} }
public static String getClosestString(String input, Iterable<String> options) { private static int distance(CharSequence lhs, CharSequence rhs) {
int lowestDistance = 10; int len0 = lhs.length() + 1;
String lowest = ""; int len1 = rhs.length() + 1;
for (String string : options) { // the array of distances
int distance = getLevenshteinDistance(input, string); int[] cost = new int[len0];
if (distance < lowestDistance) { int[] newcost = new int[len0];
lowestDistance = distance;
lowest = string;
}
}
return lowest; // initial cost of skipping prefix in String s0
} for (int i = 0; i < len0; i++) cost[i] = i;
private static int getLevenshteinDistance(String s, String t) { // dynamically computing the array of distances
if (s == null || t == null) {
return 11;
}
int n = s.length(); // transformation cost for each letter in s1
int m = t.length(); for (int j = 1; j < len1; j++) {
// initial cost of skipping prefix in String s1
newcost[0] = j;
if (n == 0) { // transformation cost for each letter in s0
return m; for (int i = 1; i < len0; i++) {
} else if (m == 0) { // matching current letters in both strings
return n; int match = (lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1;
}
if (n > m) { // computing cost for each transformation
String tmp = s; int cost_replace = cost[i - 1] + match;
s = t; int cost_insert = cost[i] + 1;
t = tmp; int cost_delete = newcost[i - 1] + 1;
n = m;
m = t.length();
}
int p[] = new int[n + 1]; // keep minimum cost
int d[] = new int[n + 1]; newcost[i] = Math.min(Math.min(cost_insert, cost_delete), cost_replace);
int _d[];
int i;
int j;
char t_j;
int cost;
for (i = 0; i <= n; i++) {
p[i] = i;
}
for (j = 1; j <= m; j++) {
t_j = t.charAt(j - 1);
d[0] = j;
for (i = 1; i <= n; i++) {
cost = s.charAt(i - 1) == t_j ? 0 : 1;
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
} }
_d = p; // swap cost/newcost arrays
p = d; int[] swap = cost;
d = _d; cost = newcost;
newcost = swap;
} }
return p[n]; return cost[len0 - 1];
} }
} }