Dada una enorme base de datos de palabras permitidas (ordenadas alfabéticamente) y una palabra, encuentre la palabra de la base de datos que esté más cerca de la palabra dada en términos de distancia de Levenshtein.
El enfoque ingenuo es, por supuesto, simplemente calcular la distancia levenshtein entre la palabra dada y todas las palabras en el diccionario (podemos hacer una búsqueda binaria en la base de datos antes de calcular las distancias).
Me pregunto si hay una solución más eficiente para este problema. Tal vez alguna heurística que nos permita reducir la cantidad de palabras a buscar, u optimizaciones al algoritmo de distancia levenshtein.
Enlaces a documentos sobre el tema de bienvenida.
fuente
Autómatas de Levenshtein: http://en.wikipedia.org/wiki/Levenshtein_automaton
Árboles BK: http://en.wikipedia.org/wiki/BK-tree
fuente
Si tiene una pequeña cantidad de ediciones incorrectas que va a tolerar, puede intentar usar un árbol de sufijos punteado . Descargo de responsabilidad: escribí ese documento, pero resuelve lo que quiere: tiene un alto costo de espacio en disco, pero las consultas son realmente rápidas.
En general, es mejor mirarlo al revés: tiene un índice de todas las palabras en el diccionario. Ahora, para una palabra de entrada w, si está en el diccionario, deténgase. De lo contrario, genere todas las variaciones a la distancia 1 y búsquelas. Si no están allí, busque variaciones a la distancia 2, y así sucesivamente ...
Hay varias mejoras a esta idea básica.
fuente
fuente
Escribí una respuesta a una pregunta muy similar en cs.stackexchange.com ( /cs//a/2096/1490 ) y luego encontré esta pregunta. La respuesta allí es una búsqueda aproximada de vecino cercano en la distancia de edición (es decir, el algoritmo genera una cadena que está aproximadamente tan cerca de la cadena de consulta como el vecino más cercano de la cadena de consulta). Estoy publicando aquí ya que no encuentro ninguna de las referencias que di allí en las respuestas dadas aquí.
fuente
Creo que lo que quiere es el algoritmo de Wagner-Fischer: https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm La idea clave es que, dado que el diccionario que está atravesando está ordenado, dos palabras consecutivas es muy probable que comparta un prefijo largo, por lo que no necesita actualizar toda la matriz para cada cálculo de distancia.
fuente
Puedes usar ¿Quiso decir?
Y luego encuentre la distancia de Levenshtein entre la respuesta devuelta por "Quiso decir" y la cadena de entrada usando la Programación dinámica.
fuente
Did you mean?
funciones. Además,Did you mean?
devuelve la palabra que está muy cerca de la entrada dada y lo hace de manera bastante eficiente. :)Una forma es entrenar un modelo de aprendizaje automático para mapear las palabras a vectores y mapear la distancia levenshtein a la distancia euclidiana. Luego puede construir un KDTree a partir de los vectores para el diccionario que desea usar. Creé un cuaderno jupyter que hace esto aquí: https://gist.github.com/MichaelSnowden/9b8b1e662c98c514d571f4d5c20c3a03
Según los comentarios de DW:
Resumen de la estructura del modelo:
Mis datos de entrenamiento son solo cadenas aleatorias, pero creo que los resultados realmente podrían mejorar si los datos de entrenamiento fueran pares (error tipográfico / palabra correcta). Terminé usando
/usr/share/dict/words
porque está comúnmente disponible.fuente