La distance de Levenshtein mesure la similarité entre deux chaînes de caractères. Elle est égale au nombre minimal de caractères qu'il faut supprimer, insérer ou remplacer pour passer d’une chaîne à l’autre.
Son nom provient de Vladimir Levenshtein qui l'a définie en 1965. Elle est aussi connue sous le nom de « distance d'édition » ou encore de « déformation dynamique temporelle », notamment en reconnaissance vocale.
Cette distance est d'autant plus grande que le nombre de différences entre les deux chaînes est grand. La distance de Levenshtein peut être considérée comme une généralisation de la distance de Hamming. On peut montrer en particulier que la distance de Hamming est un majorant de la distance de Levenshtein.
On appelle distance de Levenshtein entre deux mots M et P le coût minimal pour aller de M à P en effectuant les opérations élémentaires suivantes:
On associe ainsi à chacune de ces opérations un coût. Par exemple, dans les exemples suivants, le coût est toujours égal à 1, sauf dans le cas d'une substitution de caractères identiques.
L’algorithme ci-dessous permet de calculer la distance de Levenshtein entre deux chaînes de caractères courtes. Pour des chaînes de caractères plus longues (plusieurs mots), il faut utiliser les algorithmes de Jaccard ou TF-IDF par exemple. L’algorithme de Levenshtein est un algorithme de programmation dynamique (solution de type du bas en haut), qui utilise une matrice de dimension
entier DistanceDeLevenshtein(caractere chaine1[1..longueurChaine1], caractere chaine2[1..longueurChaine2]) // d est un tableau de longueurChaine1+1 rangées et longueurChaine2+1 colonnes declarer entier d[0..longueurChaine1, 0..longueurChaine2] // i et j itèrent sur chaine1 et chaine2 declarer entier i, j, coût pour i de 0 à longueurChaine1 d[i, 0]:= i pour j de 0 à longueurChaine2 d[0, j]:= j pour i de 1 à longueurChaine1 pour j de 1 à longueurChaine2 si chaine1[i-1] = chaine2[j-1] alors coût:= 0 sinon coût:= 1 d[i, j]:= minimum( d[i-1, j ] + 1, // effacement d[i, j-1] + 1, // insertion d[i-1, j-1] + coût // substitution ) retourner d[longueurChaine1, longueurChaine2]
L’invariant est qu’on peut transformer le segment initial chaine1[1..i]
en chaine2[1..j]
en utilisant un nombre minimal de d[i, j]
opérations. L’algorithme achevé, la solution est contenue dans la dernière position à droite de la rangée du bas de la matrice.
L’algorithme présenté a une complexité temporelle et spatiale de
D’autre part, il est aussi possible d’expliciter les suites d'opérations permettant de réellement passer d’une chaîne à l'autre. Une fois le calcul effectué, on peut obtenir ces suites en partant de la cellule en bas à droite et en remontant de cellule en cellule en prenant à chaque fois la ou les cellules à l’origine de la valeur minimum. Plusieurs cellules pouvant être à l’origine de cette valeur minimum, aussi plusieurs chemins peuvent être déduits, ils sont tous de longueur minimum. Ce processus permet par exemple d’apparier les caractères de a avec ceux de b.
Des implémentations plus complexes mais plus performantes existent par exemple celle de Myers dont le coût est en O(ND) avec D la distance et surtout celle de Wu, Manber et Myers en O(NP) ou P=D/2 − (N −M)/2.
Plusieurs implémentations sont disponibles : Levenshtein distance.