Distancia Damerau-Levenshtein - Damerau–Levenshtein distance

En teoría de la información e informática , la distancia Damerau-Levenshtein (llamada así por Frederick J. Damerau y Vladimir I. Levenshtein ) es una métrica de cadena para medir la distancia de edición entre dos secuencias. De manera informal, la distancia Damerau-Levenshtein entre dos palabras es el número mínimo de operaciones (que consisten en inserciones, eliminaciones o sustituciones de un solo carácter, o transposición de dos caracteres adyacentes) necesarias para cambiar una palabra por la otra.

La distancia Damerau-Levenshtein difiere de la distancia clásica de Levenshtein al incluir transposiciones entre sus operaciones permitidas además de las tres operaciones clásicas de edición de un solo carácter (inserciones, eliminaciones y sustituciones).

En su artículo fundamental, Damerau afirmó que en una investigación de errores ortográficos para un sistema de recuperación de información, más del 80% eran el resultado de un solo error de uno de los cuatro tipos. El artículo de Damerau consideró solo los errores ortográficos que podrían corregirse con como máximo una operación de edición. Si bien la motivación original era medir la distancia entre errores ortográficos humanos para mejorar aplicaciones como los correctores ortográficos , la distancia Damerau-Levenshtein también se ha utilizado en biología para medir la variación entre secuencias de proteínas.

Definición

Para expresar la distancia Damerau-Levenshtein entre dos cadenas y , se define una función , cuyo valor es una distancia entre un prefijo -símbolo (subcadena inicial) de cadena y un prefijo -símbolo de .

La función de distancia restringida se define de forma recursiva como:

donde es la función del indicador igual a 0 cuando e igual a 1 en caso contrario.

Cada llamada recursiva coincide con uno de los casos cubiertos por la distancia Damerau-Levenshtein:

  • corresponde a una supresión (de a a b ),
  • corresponde a una inserción (de a a b ),
  • corresponde a una coincidencia o discordancia, dependiendo de si los símbolos respectivos son iguales,
  • corresponde a una transposición entre dos símbolos sucesivos.

La distancia Damerau-Levenshtein entre una y b viene dada entonces por el valor de la función para las cadenas completas: , donde denota la longitud de cadena de

una , y es la longitud de b .

Algoritmo

Aquí se presentan dos algoritmos: el primero, más simple, calcula lo que se conoce como la distancia de alineación de cuerda óptima o distancia de edición restringida , mientras que el segundo calcula la distancia Damerau-Levenshtein con transposiciones adyacentes. Agregar transposiciones agrega una complejidad significativa. La diferencia entre los dos algoritmos consiste en que el algoritmo de alineación de cadenas óptima calcula el número de operaciones de edición necesarias para igualar las cadenas con la condición de que ninguna subcadena se edite

más de una vez , mientras que el segundo no presenta tal restricción.

Tomemos, por ejemplo, la distancia de edición entre CA y ABC . La distancia Damerau-Levenshtein LD ( CAABC ) = 2 porque CAACABC , pero la distancia de alineación de la cuerda óptima OSA ( CAABC ) = 3 porque si se usa la operación CAAC , no es posible usar ACABC porque eso requeriría que la subcadena se edite más de una vez, lo cual no está permitido en OSA y, por lo tanto, la secuencia más corta de operaciones es CAAABABC . Tenga en cuenta que para la distancia de alineación de cadena óptima, la desigualdad del

triángulo no se mantiene: OSA ( CAAC ) + OSA ( ACABC ) <OSA ( CAABC ), por lo que no es una métrica verdadera.

Distancia óptima de alineación de cuerdas

La distancia de alineación óptima de la cuerda se puede calcular utilizando una extensión sencilla del algoritmo de

programación dinámica de Wagner-Fischer que calcula la distancia de Levenshtein . En pseudocódigo :
algorithm OSA-distance is
    input: strings a[1..length(a)], b[1..length(b)]
    output: distance, integer
    
    let d[0..length(a), 0..length(b)] be a 2-d array of integers, dimensions length(a)+1, length(b)+1
    // note that d is zero-indexed, while a and b are one-indexed.
    
    for i := 0 to length(a) inclusive do
        d[i, 0] := i
    for j := 0 to length(b) inclusive do
        d[0, j] := j
    
    for i := 1 to length(a) inclusive do
        for j := 1 to length(b) inclusive do
            if a[i] = b[j] then
                cost := 0
            else
                cost := 1
            d[i, j] := minimum(d[i-1, j] + 1,     // deletion
                               d[i, j-1] + 1,     // insertion
                               d[i-1, j-1] + cost)  // substitution
            if i > 1 and j > 1 and a[i] = b[j-1] and a[i-1] = b[j] then
                d[i, j] := minimum(d[i, j],
                                   d[i-2, j-2] + 1)  // transposition
    return d[length(a), length(b)]

La diferencia con el algoritmo para la distancia de Levenshtein es la adición de una recurrencia:

if i > 1 and j > 1 and a[i] = b[j-1] and a[i-1] = b[j] then
    d[i, j] := minimum(d[i, j],
                       d[i-2, j-2] + 1)  // transposition

Distancia con transposiciones adyacentes

El siguiente algoritmo calcula la verdadera distancia Damerau-Levenshtein con transposiciones adyacentes; este algoritmo requiere como parámetro adicional el tamaño del alfabeto Σ , de modo que todas las entradas de los arreglos estén en [0, | Σ |) :

algorithm DL-distance is
    input: strings a[1..length(a)], b[1..length(b)]
    output: distance, integer
    
    da := new array of |Σ| integers
    for i := 1 to |Σ| inclusive do
        da[i] := 0
    
    let d[−1..length(a), −1..length(b)] be a 2-d array of integers, dimensions length(a)+2, length(b)+2
    // note that d has indices starting at −1, while a, b and da are one-indexed.
    
    maxdist := length(a) + length(b)
    d[−1, −1] := maxdist
    for i := 0 to length(a) inclusive do
        d[i, −1] := maxdist
        d[i, 0] := i
    for j := 0 to length(b) inclusive do
        d[−1, j] := maxdist
        d[0, j] := j
    
    for i := 1 to length(a) inclusive do
        db := 0
        for j := 1 to length(b) inclusive do
            k := da[b[j]]
            ℓ := db
            if a[i] = b[j] then
                cost := 0
                db := j
            else
                cost := 1
            d[i, j] := minimum(d[i−1, j−1] + cost,  //substitution
                               d[i,   j−1] + 1,     //insertion
                               d[i−1, j  ] + 1,     //deletion
                               d[k−1, ℓ−1] + (i−k−1) + 1 + (j-ℓ−1)) //transposition
        da[a[i]] := i
    return d[length(a), length(b)]

Para diseñar un algoritmo adecuado para calcular la distancia Damerau-Levenshtein sin restricciones, tenga en cuenta que siempre existe una secuencia óptima de operaciones de edición, donde las letras una vez transpuestas nunca se modifican posteriormente. (Esto es válido siempre que el costo de una transposición,, sea ​​al menos el promedio del costo de una inserción y eliminación, es decir, ). Por lo tanto, necesitamos considerar solo dos formas simétricas de modificar una subcadena más de una vez: ( 1) transponer letras e insertar una cantidad arbitraria de caracteres entre ellas, o (2) eliminar una secuencia de caracteres y transponer letras que se vuelven adyacentes después de la eliminación. La implementación sencilla de esta idea proporciona un algoritmo de complejidad cúbica:, donde

M y N son longitudes de cadena. Usando las ideas de Lowrance y Wagner, este algoritmo ingenuo se puede mejorar para estar en el peor de los casos, que es lo que hace el pseudocódigo anterior.

Es interesante que el algoritmo bitap pueda modificarse para procesar la transposición. Consulte la sección de recuperación de información de para ver un ejemplo de dicha adaptación.

Aplicaciones

La distancia Damerau-Levenshtein juega un papel importante en el procesamiento del lenguaje natural . En los lenguajes naturales, las cadenas son cortas y el número de errores (errores ortográficos) rara vez excede 2. En tales circunstancias, la distancia de edición restringida y real difieren muy raramente. Oommen y Loke incluso mitigaron la limitación de la distancia de edición restringida al introducir transposiciones generalizadas . Sin embargo, uno debe recordar que la distancia de edición restringida generalmente no satisface la desigualdad del

triángulo y, por lo tanto, no se puede usar con árboles métricos .

ADN

Dado que el ADN experimenta con frecuencia inserciones, deleciones, sustituciones y transposiciones, y cada una de estas operaciones ocurre aproximadamente en la misma escala de tiempo, la distancia Damerau-Levenshtein es una métrica apropiada de la variación entre dos cadenas de ADN. Más común en el ADN, las proteínas y otras tareas de alineación relacionadas con la bioinformática es el uso de algoritmos estrechamente relacionados, como el algoritmo Needleman-Wunsch o el

algoritmo Smith-Waterman .

Detección de fraudes

El algoritmo se puede utilizar con cualquier conjunto de palabras, como nombres de proveedores. Dado que el ingreso es manual por naturaleza, existe el riesgo de ingresar un proveedor falso. Un empleado estafador puede ingresar un proveedor real como "Rich Heir Estate Services" versus un proveedor falso "Rich Hier State Services". El defraudador crearía una cuenta bancaria falsa y haría que la empresa enviara los cheques al proveedor real y al proveedor falso. El algoritmo Damerau-Levenshtein detectará la letra transpuesta y descartada y llamará la atención sobre los elementos a un examinador de fraudes.

Control de exportación

El gobierno de EE. UU. Utiliza la distancia Damerau-Levenshtein con su API de lista de cribado consolidada.

Ver también

Referencias

Otras lecturas