package yuku.alkitab.base.util;
import android.widget.Toast;
import yuku.alkitab.base.App;
import yuku.alkitab.util.IntArrayList;
import java.util.ArrayList;
import java.util.List;
public class Levenshtein {
private static final int insertion = 100;
private static final int deletion = 500;
private static final int substitution = 400;
public static int distance(String s, String t) {
try {
return distance0(s, t);
} catch (Exception e) {
Toast.makeText(App.context, "Unexpected exception!\n\n" + e.getClass().getName() + " " + e.getMessage(), Toast.LENGTH_SHORT).show();
return distanceSlow(s, t);
}
}
private static int distance0(String s, String t) {
// d is a table with m+1 rows and n+1 columns
final int m = s.length();
final int n = t.length();
final int[][] d = new int[m + 1][n + 1];
for (int i = 0; i <= m; i++) {
d[i][0] = i * deletion; // deletion
}
for (int j = 0; j <= n; j++) {
d[0][j] = j * insertion; // insertion
}
for (int j = 1; j <= n; j++) { // j is the index to t
for (int i = 1; i <= m; i++) { // i is the index to s
if (s.charAt(i - 1) == t.charAt(j - 1)) {
d[i][j] = d[i - 1][j - 1] + j + j; // the longer the offset difference between the same character, the less relevant it is
} else {
d[i][j] = minimum(
d[i - 1][j] + deletion, // deletion
d[i][j - 1] + insertion + (j - i), // insertion
d[i - 1][j - 1] + substitution // substitution
);
}
}
}
return d[m][n];
}
private static int distanceSlow(String s, String t) {
// d is a table with m+1 rows and n+1 columns
final int m = s.length();
final int n = t.length();
List<IntArrayList> d = new ArrayList<>();
for (int i = 0; i < m + 1; i++) {
final IntArrayList a = new IntArrayList(n + 1);
d.add(a);
for (int j = 0; j < n + 1; j++) {
a.add(0);
}
}
for (int i = 0; i <= m; i++) {
d.get(i).set(0, i * deletion); // deletion
}
for (int j = 0; j <= n; j++) {
d.get(0).set(j, j * insertion); // insertion
}
for (int j = 1; j <= n; j++) { // j is the index to t
for (int i = 1; i <= m; i++) { // i is the index to s
if (s.charAt(i - 1) == t.charAt(j - 1)) {
d.get(i).set(j, d.get(i - 1).get(j - 1) + j + j); // the longer the offset difference between the same character, the less relevant it is
} else {
d.get(i).set(j, minimum(
d.get(i - 1).get(j) + deletion, // deletion
d.get(i).get(j - 1) + insertion + (j - i), // insertion
d.get(i - 1).get(j - 1) + substitution // substitution
));
}
}
}
return d.get(m).get(n);
}
private static int minimum(int a, int b, int c) {
int d = (a < b) ? a : b;
return (c < d) ? c : d;
}
}