Cómo hacer búsquedas difusas eficientes usando la distancia levenshtein

En primer lugar, tienes tu notación Big Oh completamente equivocada. No puede mezclar el tamaño de su cuerpo (número de teclas) con el tamaño de las teclas. El cálculo de Levenshtein solo depende del tamaño de la clave y la consulta, y cada clave, como dijiste, es de 1 a 5 elementos o quizás 100. No importa porque es CONSTANTE fijo en la longitud máxima de la clave si quieres un límite superior.
Por lo tanto, su algoritmo siempre es O (n) independientemente de cómo calcule Levenshtein. Puede ser O (n * 100 * 100) u O (n * 5 * 5) pero sigue siendo lineal.

Dicho esto, a veces O (n) no siempre es aceptable, si tiene millones de claves, es posible que no desee probar cada clave para su consulta. Una forma de resolver eso es indexar n-gramos o las rotaciones de sus teclas para cada tecla y luego buscar los n-gramos o rotaciones que puede extraer de su consulta. Luego, sobre las teclas recuperadas, verifique si la distancia de Levenshtein coincide o no con la consulta.

Por ejemplo, si tiene una clave “hola” y utiliza rotaciones, indexa:

hola $
ello $ h
llo $ he
lo $ hel
o $ infierno
$ hola

(todos apuntando a la tecla “hola”)

Luego, cuando su consulta sea “hola”, puede buscar rotaciones como “ello *” “h *”, “o $ *”, etc. no buscará en todo el conjunto de llaves. Entonces estarás en una complejidad sub-lineal.

Si la distancia es 1, es muy fácil construir las rotaciones que son útiles para usted, ya que sus opciones son eliminar un carácter de la consulta o agregar un carácter a la consulta. Si la distancia es 2, también es fácil soltar 1/2, agregar 1/2 o modificar 1.

Los N-gramos consumirán menos espacio que las rotaciones, pero tienen más falsos positivos.

Levenshtein con distancia 5 es realmente inusual, ya que coincidirá con teclas que realmente no tienen nada que ver con su consulta.

Todo eso se debe a su pregunta sobre cómo evitar sondear cada tecla. Ahora:

Tengo la sensación de que usar un algoritmo eficiente para calcular levenshtein y buscar linealmente cada tecla es una solución eficiente. Eche un vistazo al algoritmo bitap usando en agrep (algoritmo Bitap)

Finalmente, si clasifica sus claves y puede permitirse el lujo de no coincidir si el primer carácter es diferente, puede simplemente indexar el primer carácter de sus claves y Bitap sobre esas claves candidatas. Eso será realmente rápido y sencillo de codificar.

¡Este es un problema bastante difícil! No creo que exista una solución fácil . Sin embargo, existen soluciones que son claramente mejores que las ingenuas.

Veamos este problema como uno de optimización. Claramente, el algoritmo ingenuo va a funcionar, pero el problema es que tiene demasiadas claves para trabajar. Entonces, lo que queremos hacer es eliminar tantas claves como podamos de la manera más económica posible, y luego ejecutar el algoritmo ingenuo una vez que nos quedemos sin métodos de eliminación baratos. Esto proporciona un subconjunto del grupo total de claves que podrían estar dentro de la distancia de nivel dada.

Para que esto funcione, nos gustaría poder eliminar grandes grupos de claves sin tener que mirarlas de cerca. En cada caso, quiero asignar un límite mínimo al puntaje levenshtein; Cada vez que el puntaje aproximado de una tecla excede el límite mínimo, puedo tirarlo sin hacer ningún trabajo adicional.

Me referiré al valor que está buscando como ‘búsqueda’ y a los valores de la base de datos como ‘claves’.

1. La diferencia en longitudes aumenta el límite mínimo en al menos 1 por diferencia.
2. Cualquier letra contenida en una clave que no está contenida en la búsqueda aumenta el límite mínimo en al menos 1. Cualquier letra contenida en la búsqueda pero no en la clave aumenta el límite mínimo en al menos 1.
3. Una variante más sofisticada de # 2 sería no solo verificar la presencia / ausencia de una letra, sino la diferencia en el número de ocurrencias. Esto es más costoso, por lo que tal vez debería hacerse en una fase posterior.

La idea es combinar los resultados de estas etapas para eliminar gradualmente más y más claves, en particular, los límites mínimos de la fase 1 y la fase 2/3 se pueden sumar, lo que potencialmente permite eliminar muchas más claves rápidamente. Cuanto menor sea el puntaje permitido de levenshtein, más rápido será. Finalmente, una vez que haya hecho toda la eliminación que pueda, debe ejecutar el algoritmo ingenuo en lo que quede.

Es posible que pueda obtener algunos de los filtros debajo de O (n), pero parece bastante difícil. Es fácil hacer una tabla de búsqueda de todas las claves por longitud, pero una tabla de búsqueda de todas las claves por letras contenidas parece más difícil. ¿Quizás podría manejarlo ordenando las letras en las teclas (hola -> ehllo) y luego poniéndolas en una concordancia? Algo así, de todos modos. Todavía hay mucho pensamiento por hacer.

Lucene resolvió este problema usando una máquina de estados finitos y es realmente rápido. Para más información: Dawid Weiss- Autómatas de estados finitos en lucene

Tenga en cuenta que una distancia de Levenshtein de 5 significa que no solo encontrará “yello” para “hola”, sino que también encontrará “pez” (y cualquier otra palabra de 1 letra – 5 letras).

More Interesting

¿Cuál es la optimización de un conjunto de antenas?

¿Puedo encontrar el camino hamiltoniano más corto en un gráfico completo ponderado no dirigido en tiempo polinómico (donde todos los pesos no son negativos)?

¿Cómo se realiza la agrupación en el sondeo lineal en hashing con direccionamiento abierto?

Cómo implementar un código C para la eliminación de un nodo de una lista vinculada considerando todos los casos de prueba

Cómo contar en binario

¿Cuál es una explicación simple de por qué BFS bidireccional se ejecuta en [math] \ Theta (\ sqrt {n}) [/ math]?

¿Qué método se ejecuta más rápido para una matriz con todas las claves idénticas, tipo burbuja o tipo inserción?

¿Cómo es posible que el hashing sea imposible de revertir? ¿Hay alguna prueba?

¿Cuándo se usaría un algoritmo gráfico?

¿Cuál es el mejor algoritmo de aprendizaje profundo sin supervisión para aprender características de los datos de secuencia biológica?

Los electrones son extraños. ¿Cómo conocen el camino más corto al suelo? ¿No tendrían que 'mirar' hacia adelante?

¿Necesito matemáticas para aprender estructuras de datos y algoritmos?

¿Existe un método o algoritmo matemático para expresar la suma de un número y un número multiplicado por un radical como la fórmula (a + b) ^ 3?

¿Qué algoritmo de compresión de imagen se usa en WhatsApp?

¿Cuáles son los algoritmos de nivel básico con los que debemos comenzar y cuáles son los algoritmos avanzados que debemos estudiar?