Sto lavorando a un'implementazione di ricerca fuzzy e, come parte dell'implementazione, stiamo utilizzando Stringiclics.getLevenshteinDistance di Apache. Al momento, stiamo andando per un tempo di risposta medio maxmimum specifico per la nostra ricerca fuzzy. Dopo vari miglioramenti e con alcuni profili, il luogo in cui viene speso il maggior tempo è il calcolo della distanza di Levenshtein. Impiega all'incirca l'80-90% del tempo totale nelle stringhe di ricerca tre o più lettere.Modifica dell'algoritmo della distanza di Levenshtein per non calcolare tutte le distanze
Ora, so che ci sono alcune limitazioni a ciò che può essere fatto qui, ma ho letto su domande SO precedenti e sul link Wikipedia per LD che se uno è disposto a limitare la soglia ad una distanza massima impostata, che potrebbe aiutare a limitare il tempo trascorso nell'algoritmo, ma non sono sicuro di come farlo esattamente.
Se ci interessa solamente nella distanza se è più piccolo di un soglia k, allora è sufficiente calcolare una striscia diagonale di larghezza 2k + 1 nella matrice. In questo modo, l'algoritmo può essere eseguito in tempo O (kl), dove l è la lunghezza della stringa più breve [3].
Qui sotto vedrete il codice LH originale da StringUtils. Dopo che è la mia modifica. Sto cercando di calcolare fondamentalmente le distanze di una lunghezza impostata dalla diagonale i, j (quindi, nel mio esempio, due diagonali sopra e sotto la diagonale i, j). Tuttavia, questo non può essere corretto come ho fatto. Ad esempio, sulla diagonale più alta, sceglierà sempre il valore della cella direttamente sopra, che sarà 0. Se qualcuno mi può mostrare come renderlo funzionale come ho descritto, o qualche consiglio generale su come renderlo tale , Sarebbe molto apprezzato.
public static int getLevenshteinDistance(String s, String t) {
if (s == null || t == null) {
throw new IllegalArgumentException("Strings must not be null");
}
int n = s.length(); // length of s
int m = t.length(); // length of t
if (n == 0) {
return m;
} else if (m == 0) {
return n;
}
if (n > m) {
// swap the input strings to consume less memory
String tmp = s;
s = t;
t = tmp;
n = m;
m = t.length();
}
int p[] = new int[n+1]; //'previous' cost array, horizontally
int d[] = new int[n+1]; // cost array, horizontally
int _d[]; //placeholder to assist in swapping p and d
// indexes into strings s and t
int i; // iterates through s
int j; // iterates through t
char t_j; // jth character of t
int cost; // 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;
// minimum of cell to the left+1, to the top+1, diagonally left and up +cost
d[i] = Math.min(Math.min(d[i-1]+1, p[i]+1), p[i-1]+cost);
}
// copy current distance counts to 'previous row' distance counts
_d = p;
p = d;
d = _d;
}
// our last action in the above loop was to switch d and p, so p now
// actually has the most recent cost counts
return p[n];
}
mie modifiche (solo per il cicli for):
for (j = 1; j<=m; j++) {
t_j = t.charAt(j-1);
d[0] = j;
int k = Math.max(j-2, 1);
for (i = k; i <= Math.min(j+2, n); i++) {
cost = s.charAt(i-1)==t_j ? 0 : 1;
// minimum of cell to the left+1, to the top+1, diagonally left and up +cost
d[i] = Math.min(Math.min(d[i-1]+1, p[i]+1), p[i-1]+cost);
}
// copy current distance counts to 'previous row' distance counts
_d = p;
p = d;
d = _d;
}
pensiero appena venuto in mente che avrei potuto controllare se il valore è zero e quindi ignorarlo o sostituirlo con un valore arbitrariamente alto. Probabilmente, SHould potrebbe pensarci un po 'di più. – AHungerArtist