Lección
La teoría — Visualizador de Distancia de Levenshtein
La distancia de Levenshtein entre dos cadenas es el menor número de ediciones de un solo carácter que convierte una en la otra, siendo una edición una inserción, un borrado o una sustitución. Es un mínimo sobre todas las maneras posibles de hacerlo, y eso es justo lo que la hace difícil de estimar a ojo y fácil de calcular con una cuadrícula: hay una cantidad astronómica de secuencias de edición, y este procedimiento encuentra la más corta sin enumerar ninguna.
Qué significa cada símbolo
m, n- las longitudes de las dos cadenas, A y B.
D(i, j)- la forma más barata de convertir los i primeros caracteres de A en los j primeros caracteres de B. Una celda de la tabla de esta página.
[aᵢ ≠ bⱼ]- vale 1 cuando esos dos caracteres difieren y 0 cuando coinciden: el precio de la sustitución, que se anula si no hay nada que sustituir.
d- la respuesta,
D(m, n): la celda inferior derecha.
De dónde viene la fórmula
- Decide qué significa una celda antes de rellenar ninguna. Sea
D(i, j)el mínimo de ediciones que convierte losiprimeros caracteres de A en losjprimeros de B. El número que buscas esD(m, n), y cualquier otra celda es una versión menor de la misma pregunta. - Los bordes no exigen pensar. Para construir los
jprimeros caracteres de B partiendo de nada hay que hacerjinserciones, así queD(0, j) = j. Para reducir a nada losiprimeros de A hay que haceriborrados, así queD(i, 0) = i. Esa es la fila superior y la columna izquierda de la cuadrícula, y por eso se limitan a contar. - Ahora el paso que hace todo el trabajo. Toma cualquier guion óptimo para
D(i, j)y mira solo su último movimiento. Hay tres posibilidades y ninguna más: borróaᵢ, dejando la tareaD(i−1, j); insertóbⱼ, dejandoD(i, j−1); o emparejóaᵢconbⱼ, dejandoD(i−1, j−1). Cada una de ellas es una celda que tú ya has rellenado. - Así que la celda es la más barata de las tres:
D(i, j) = min( D(i−1, j) + 1, D(i, j−1) + 1, D(i−1, j−1) + [aᵢ ≠ bⱼ] ). Rellena la cuadrícula de izquierda a derecha y de arriba abajo, y al llegar a cualquier celda sus tres vecinas ya se conocen. Ese es el algoritmo entero:m × nceldas, tres comparaciones cada una.
Cómo leer lo que ves
La cuadrícula de esta página es esa tabla. Las filas son A, las columnas son B, y la fila y la columna extra de la esquina superior izquierda son los prefijos vacíos del paso 2, por eso cuentan 0, 1, 2, 3. El sombreado de cada celda es su valor: el pasillo diagonal pálido es donde las dos cadenas aún coinciden de forma barata. Pasa el ratón o toca cualquier celda y el panel de debajo detalla el paso 3 para esa celda concreta: los tres candidatos, cada uno con su aritmética, y el ganador resaltado. La línea de color es una ruta óptima trazada hacia atrás desde la esquina inferior derecha, y la tira de alineamiento de debajo es esa misma ruta escrita en caracteres.
- Supone
- Cada edición cuesta exactamente 1 y los caracteres se comparan por igualdad exacta: sin plegado de mayúsculas, sin normalización Unicode y sin ninguna noción de qué caracteres se parecen. Aquí se ven dos consecuencias. Lo que se cuenta aquí son unidades de código UTF-16, no lo que tú llamarías letras: escribe un solo emoji en una casilla y la tabla es de 3 × 1, porque un emoji son dos unidades y borrarlo cuesta 2. Y
cafécon unaéprecompuesta frente acaféescrito comoemás un acento combinante da distancia 2 aunque en pantalla se vean idénticos. - Falla cuando
- La cuadrícula tiene
m × nceldas, así que el trabajo crece como el producto de las longitudes. Eso está bien para dos palabras y es inviable para una consulta contra un diccionario de un millón de entradas, que son un millón de cuadrículas. La respuesta natural sería un algoritmo más astuto, y la sorpresa es que prácticamente no existe: Backurs e Indyk demostraron en 2015 que una distancia de edición fuertemente subcuadrática refutaría la hipótesis del tiempo exponencial fuerte. Los correctores ortográficos reales no baten esa cota, la esquivan: se detienen en cuanto la distancia supera un límite pequeño, o indexan de modo que casi ningún candidato llegue a compararse.
Problema resuelto al detalle
-
La secuencia de edición de menor coste para convertir kitten en sitting 5 pasos
Convierta kitten en sitting. Halle la secuencia de edición de menor coste y demuestre que no existe ninguna más económica; después, calcule cuánto cuesta esto cuando la segunda palabra es un diccionario entero.
-
La relación de recurrencia constituye todo el algoritmo. Cada casilla calcula el coste de llegar hasta ella eliminando, insertando o alineando los dos caracteres actuales (siendo esta última opción gratuita cuando coinciden). Una casilla solo necesita sus tres vecinas situadas encima y a su izquierda, de modo que un único barrido de izquierda a derecha llena la tabla.
-
Antes de rellenar nada, acote la respuesta. Las longitudes difieren en una unidad, por lo que al menos una inserción es inevitable; además, reescribir la palabra por completo cuesta 7. La respuesta se encuentra entre ambos valores, lo que descarta de entrada la mayoría de las conjeturas.
-
Tres ediciones bastan: sustituir k → s, sustituir e → i e insertar g. Cada una es una única edición válida y la cadena termina en la palabra destino.
-
Presentar tres ediciones solo demuestra que la distancia es como máximo 3. La tabla demuestra que es exactamente 3, porque se evalúa la puntuación de cada ruta hasta la esquina inferior derecha y se toma el mínimo en cada casilla del camino. Esa es la diferencia entre encontrar una respuesta y saber que no se puede superar.
-
El coste es de una casilla por cada par de caracteres: 42 en este caso, lo cual no es nada. Frente a un diccionario de 100 000 palabras de siete letras cada una, supone más de cuatro millones de actualizaciones de casilla para una sola búsqueda.
Respuesta
La herramienta indica 3 y una similitud del 57,14%, que es 1 − 3/7: la distancia normalizada por la palabra más larga. Ambos valores provienen de una tabla que se puede rellenar a mano en un minuto. Lo que no escala es la propia tabla: la complejidad es Θ(mn), de modo que duplicar ambas cadenas la cuadruplica, y todos los correctores ortográficos que ha utilizado se basan en evitar precisamente esto. La solución no pasa por calcular la tabla más rápido. Consiste en que la distancia de Levenshtein satisface la desigualdad triangular, por lo que d(a, c) ≤ d(a, b) + d(b, c) permite a un índice demostrar que un candidato está demasiado lejos sin llegar a medir la distancia exacta.
-
Referencias (4)
- The theory section ends on why nobody has a much faster algorithm. This is the result that says they probably cannot have one: A. Backurs & P. Indyk, "Edit Distance Cannot Be Computed in Strongly Subquadratic Time (Unless SETH is False)." SIAM Journal on Computing 47(3), 1087–1097, 2018; first presented at STOC 2015.
- The grid this tool fills, and why filling each cell once is enough: R. A. Wagner & M. J. Fischer, "The String-to-String Correction Problem." Journal of the ACM 21(1), 168–173, 1974 — the dynamic-programming algorithm for the edit distance Levenshtein had defined in 1965.
- The fourth move in the Damerau cost model, and the survey of typing errors that argued for it: F. J. Damerau, "A technique for computer detection and correction of spelling errors." Communications of the ACM 7(3), 171–176, 1964.
- Insight block 3 ends on the problem of recovering the route without keeping the grid. This is the paper that solved it: D. S. Hirschberg, "A linear space algorithm for computing maximal common subsequences." Communications of the ACM 18(6), 341–343, 1975.