Estoy interesado en los intentos y DAWG (gráfico de palabras acíclicas directas) y he estado leyendo mucho sobre ellos, pero no entiendo cómo debería ser el archivo trie o DAWG de salida.
- ¿Debería un trie ser objeto de diccionarios anidados? ¿Dónde cada letra se divide en letras y así sucesivamente?
- ¿Una búsqueda realizada en dicho diccionario sería rápida si hay 100k o 500k entradas?
- ¿Cómo implementar bloques de palabras que consisten en más de una palabra separada con
-
o espacio? - ¿Cómo vincular el prefijo o sufijo de una palabra a otra parte de la estructura? (para DAWG)
Quiero comprender la mejor estructura de salida para descubrir cómo crear y usar una.
También agradecería cuál debería ser la salida de un DAWG junto con trie .
No quiero ver representaciones gráficas con burbujas unidas entre sí, quiero conocer el objeto de salida una vez que un conjunto de palabras se convierten en intentos o DAWG.
Respuestas:
Relájese es esencialmente correcto que hay muchas formas diferentes de implementar un trie; y para un trie grande y escalable, los diccionarios anidados pueden volverse engorrosos, o al menos ineficientes en cuanto al espacio. Pero como recién estás comenzando, creo que ese es el enfoque más fácil; podría codificar un simple
trie
en solo unas pocas líneas. Primero, una función para construir el trie:Si no está familiarizado
setdefault
, simplemente busca una clave en el diccionario (aquíletter
o_end
). Si la clave está presente, devuelve el valor asociado; si no, asigna un valor predeterminado a esa clave y devuelve el valor ({}
o_end
). (Es como una versión deget
eso que también actualiza el diccionario).A continuación, una función para probar si la palabra está en el trie:
Te dejaré la inserción y extracción como ejercicio.
Por supuesto, la sugerencia de Unwind no sería mucho más difícil. Puede haber una ligera desventaja de velocidad en que encontrar el subnodo correcto requeriría una búsqueda lineal. Pero la búsqueda se limitaría al número de caracteres posibles: 27 si los incluimos
_end
. Además, no se gana nada al crear una lista masiva de nodos y acceder a ellos por índice, como sugiere; también podrías anidar las listas.Finalmente, agregaré que crear un gráfico de palabras acíclicas dirigido (DAWG) sería un poco más complejo, porque debe detectar situaciones en las que su palabra actual comparte un sufijo con otra palabra en la estructura. De hecho, esto puede ser bastante complejo, dependiendo de cómo desee estructurar el DAWG. Es posible que tenga que aprender algunas cosas sobre la distancia de Levenshtein para hacerlo bien.
fuente
dict.setdefault()
(está subutilizado y no es lo suficientemente conocido), en parte porque ayuda a prevenir errores que son demasiado fáciles de crear con undefaultdict
(donde no obtendríasKeyError
claves no existentes en la indexación). Lo único que lo haría utilizable para el código de producción es usar_end = object()
:-)Echa un vistazo a esto:
https://github.com/kmike/marisa-trie
Aquí hay una publicación de blog de una empresa que utiliza marisa trie con éxito:
https://www.repustate.com/blog/sharing-large-data-structure-across-processes-python/
También hay un par de implementaciones de Python puro, aunque a menos que esté en una plataforma restringida, desearía usar la implementación respaldada por C ++ anterior para obtener el mejor rendimiento:
fuente
Aquí hay una lista de paquetes de Python que implementan Trie:
fuente
Modificado del
senderle
método de (arriba). Descubrí que Pythondefaultdict
es ideal para crear un árbol o un árbol de prefijos.fuente
No hay "debería"; tu decides. Varias implementaciones tendrán diferentes características de rendimiento, tomarán diferentes cantidades de tiempo para implementar, comprender y acertar. Esto es típico para el desarrollo de software en su conjunto, en mi opinión.
Probablemente primero intente tener una lista global de todos los nodos de trie creados hasta ahora, y representar los punteros secundarios en cada nodo como una lista de índices en la lista global. Para mí, tener un diccionario solo para representar la vinculación del niño me parece demasiado pesado.
fuente
Si desea implementar un TRIE como una clase de Python, aquí hay algo que escribí después de leer sobre ellos:
fuente
Esta versión está usando recursividad
Salida:
fuente
Define Trie:
Crea Trie:
Buscar:
Prueba:
fuente
True
solo se devuelve para una palabra completa, pero no para el prefijo, para el cambio de prefijoreturn '_end' in curr
areturn True
Fuera
fuente
Clase de Python para Trie
La estructura de datos Trie se puede usar para almacenar datos en
O(L)
donde L es la longitud de la cadena, por lo que para insertar N cadenas, la complejidad del tiempo sería queO(NL)
la cadena se puede buscarO(L)
solo para eliminarla.Se puede clonar desde https://github.com/Parikshit22/pytrie.git
Oputpt de código
Verdadero
Falso
['minakshi', 'minhaj']
7
minakshi
minhajsir
pari
parikshit
shubh
shubham
shubhi
fuente