Abbina due stringhe ma consente un grado di errore


10

Come posso abbinare due stringhe, ma allo stesso tempo consentire che il numero X di caratteri sia errato nella corrispondenza. Il numero di errori dovrebbe essere una variabile controllabile.

Mentre il numero X di caratteri non può corrispondere nella stringa, ci dovrebbe essere un limite su quanti corrono in una sequenza. Date due stringhe potrei consentire a 5 caratteri di essere diversi, ma non più di 2 di fila.

Sto cercando un algoritmo consigliato per confrontare queste due stringhe, o forse esiste già una soluzione nota per questo.


4
La distanza di Levenshtein potrebbe essere qualcosa da guardare, sebbene i dettagli del "non più di 2 di fila" non facciano parte di tale algoritmo. La pagina vedi anche ha molti altri algoritmi correlati che potrebbero essere quello che stai cercando.

@MichaelT se avessi qualcosa del genere si adatterebbe sicuramente alle mie esigenze. Grazie.
Reactgular

@MichaelT Ho trovato questo> dotnetperls.com/levenshtein Dovresti dirlo perché la risposta ha risolto i miei problemi.
Reactgular,

Potresti voler guardare la corrispondenza Soundex. en.wikipedia.org/wiki/Soundex
Gilbert Le Blanc

Risposte:


12

Un punto di partenza approssimativo per la ricerca di stringhe è quello del distanza di Levenshtein . Questo algoritmo conta il numero di modifiche a carattere singolo (inserisci, elimina e sostituisci) per cambiare una parola in un'altra.

Un esempio di questo è kitten -> sittingche ha una distanza di modifica di tre

  1. k itten -> s itten (sostituisce 's' per 'k')
  2. sitt e n -> sitt i n (sostituisci "i" con "e")
  3. sittin -> sittin g (aggiungi 'g' alla fine)

Ci sono variazioni su questo algoritmo, in particolare il distanza Damerau-Levenshtein che consente la trasposizione di due caratteri adiacenti ("hte" a "the" ha una distanza DL di 1 e una distanza di Levenshtein di 2) e quindi è spesso più appropriato per controllo ortografico. Esistono altre varianti per applicazioni in cui le lacune sono importanti (stringhe di DNA).

La distanza di Levenshtein è ben nota e non troppo difficile da trovare (una volta avevo motivo di cercarne un'implementazione come una funzione in oracolo : era molto più veloce che abbattere tutti i dati e quindi eseguire il lato del codice di query). Rosettacode ha una moltitudine (54) di implementazioni della distanza Levenshtein (nota che alcune lingue hanno questo come parte della libreria di stringhe da qualche parte - se stai facendo Java, guarda l' apache commons lang ). Wikibooks ha 31 implementazioni e uno sguardo veloce ai due non mostra lo stesso codice per la stessa lingua.

Il modo in cui funziona è che crea una matrice che corrisponde alla relazione tra le due stringhe:

 .kitten
.0123456
s1123456
i2212345
t3321234
t4432123
i5543223
n6654332
g7765443

Il . riga e la colonna indicano che è possibile raggiungere la stringa target inserendo "solo" ogni lettera da una stringa vuota. Questo non è il caso ideale, ma è lì per seminare l'algoritmo.

Se il valore è lo stesso di quello spot ('i' == 'i'), il valore è uguale al valore in diagonale verso sinistra. Se i due punti sono diversi ('s'! = 'K') il valore è il minimo di:

  • diagonale verso l'alto e verso sinistra + 1 (una sostituzione)
  • direttamente sopra + 1 (un inserimento)
  • direttamente a sinistra + 1 (una cancellazione)

Il valore di ritorno della distanza di modifica è il valore in basso a destra della matrice.

Se segui da in basso a destra in alto a sinistra con il minimo, puoi vedere le modifiche fatte:

 .kitten
.0.   .
s.1   .
i  1  .
t   1 .
t    1.
i.....2
n      2
g......3

Si noti che questo è l'approccio piuttosto intensivo di memoria. Può essere ridotto nell'ambito della memoria non costruendo la matrice completa: tutto l'algoritmo a cui importa è un sottoinsieme dei dati e può essere ridotto da N*Mspazio a 2*max(N,M)spazio semplicemente memorizzando la riga precedente (e ciò che è stato calcolato sull'attuale riga). Code Project mostra come eseguire questa operazione (con il codice C # da scaricare).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.