2010-03-21 54 views
34

Qué estructura proporciona los mejores resultados de rendimiento; trie (árbol de prefijos), árbol de sufijos o matriz de sufijos? ¿Hay otras estructuras similares? ¿Cuáles son las buenas implementaciones de Java de estas estructuras?Trie vs. suffix tree vs. sufijo array

Editar: en este caso quiero hacer una coincidencia de cadenas entre un gran diccionario de nombres y un gran conjunto de textos en lenguaje natural, con el fin de identificar los nombres del diccionario en los textos.

+8

¿El mejor rendimiento para qué operaciones? –

Respuesta

52

El trie fue la primera estructura de datos de este tipo descubierta.

El árbol de sufijo es una mejora sobre el trie (tiene enlaces de sufijo que permiten la búsqueda de error lineal, el árbol de sufijo recorta las ramas innecesarias del trie, por lo tanto, no requiere tanto espacio).

La matriz de sufijos es una estructura de datos simplificada basada en el árbol de sufijos (sin enlaces de sufijos (coincidencias de errores lentos), aunque la coincidencia de patrones es muy rápida).

El trie no es para uso en el mundo real porque consume demasiado espacio.

El árbol de sufijo es más ligero y más rápido que el trie y se usa para indexar el ADN u optimizar algunos grandes motores de búsqueda web.

La matriz de sufijos es más lenta en algunas búsquedas de patrones que en el árbol de sufijos, pero ocupa menos espacio y es más utilizada que el árbol Suffix.

En la misma familia de estructuras de datos:

Hay otras implementaciones, el CST es una implementación del árbol de sufijos utilizando un arreglo de sufijos y algunas estructuras de datos adicionales para obtener algunas de las capacidades de búsqueda de árbol de sufijos.

El FCST lo lleva más lejos, implementa un árbol de sufijo muestreado con una matriz de sufijos.

El DFCST es una versión dinámica del FCST.

Ampliación:

Los dos factores importantes son el uso del espacio y el tiempo de ejecución de la operación. Se podría pensar que con las máquinas modernas esto no es relevante, pero para indexar el ADN de un solo ser humano requeriría 40 gigabytes de memoria (utilizando un árbol de sufijo descomprimido y no optimizado). Y construir uno de estos índices sobre esta cantidad de datos puede llevar días. Imagine Google, tiene muchos datos de búsqueda, necesitan un gran índice sobre todos los datos web y no lo cambian cada vez que alguien construye una página web. Tienen alguna forma de almacenamiento en caché para eso. Sin embargo, el índice principal probablemente sea estático. Y cada dos semanas más o menos reúnen todos los nuevos sitios web y datos y crean un nuevo índice, que reemplaza al antiguo cuando termina el nuevo. No sé qué algoritmo usan para indexar, pero probablemente sea un arreglo de sufijo con propiedades de árbol de sufijo sobre una base de datos particionada.

El CST utiliza 8 gigabytes, sin embargo, la velocidad de las operaciones del árbol de sufijo se reduce considerablemente.

El conjunto de sufijos puede hacer lo mismo en unos 700 megas a 2 Gigas. Sin embargo, no encontrará errores genéticos en el ADN con una matriz de sufijos (lo que significa que buscar un patrón con un comodín es mucho más lento).

El FCST (árbol de sufijo totalmente comprimido) puede crear un árbol de sufijos en 800 a 1.5 gigas. Con un deterioro de velocidad bastante pequeño hacia el CST.

El DFCST utiliza un 20% más de espacio que el FCST y pierde velocidad en la implementación estática del FCST (sin embargo, un índice dinámico es muy importante).

No hay muchas implementaciones viables (espacio-sabio) del árbol de sufijo porque es muy difícil hacer que las operaciones aceleren la compensación de las estructuras de datos del costo de espacio de RAM.

Dicho esto, el árbol de sufijo tiene resultados de búsqueda muy interesantes para la coincidencia de patrones con errores. El aho corasick no es tan rápido (aunque es casi tan rápido para algunas operaciones, no coincide con el error) y el Boyer Moore queda en el polvo.

+3

¿Qué es "lineal"? búsqueda de error "? –

+5

La búsqueda de error lineal es una búsqueda de error que devuelve todas las posibles coincidencias de error en tiempo lineal. Por ejemplo, un texto tiene las palabras "Casa", "Housa", "Hotse" en algún lado. Una coincidencia de error constante devolvería todos los errores en una sola operación. La coincidencia de error lineal devuelve todos los errores (coincidencias) en COUNT (coincidencias). En este caso 2. Algunos podrían interpretar esto como una búsqueda lineal en el tamaño del texto (escaneo de texto para el error), y por lo tanto el costo sería igual al tamaño del texto. Que es el caso de casi todos los algoritmos de búsqueda de errores, sin embargo, no es el caso para el árbol de sufijos. –

+1

La ventaja de la matriz de sufijos es que utiliza menos espacio que el árbol de sufijos. Pero, ¿cómo podemos saber eso? ¿Hay alguna prueba matemática o nos basamos en los experimentos prácticos? –

2

Usando Suffix Trees puede escribir algo que unirá su diccionario a su texto en O (n + m + k) tiempo donde n es letras en su diccionario, m es letras en su texto, yk es el número de partidos. Las pruebas son mucho más lentas para esto. No estoy seguro de qué es una matriz de sufijos, así que no puedo comentar sobre eso.

Dicho esto, no es trivial codificar y no sé de ninguna biblioteca de Java que proporcione las funciones necesarias.

+0

Acerca de las matrices de sufijos: http://en.wikipedia.org/wiki/Suffix_array –

+0

Sí, he estado leyendo sobre matrices de sufijos. Resulta que tienen la misma velocidad asintótica que los árboles Suffix, pero son más eficientes en cuanto a espacio. Definitivamente son una opción. – swestrup

1

EDIT: En este caso quiero hacer la coincidencia de cadenas entre un gran diccionario de nombres y un gran conjunto de textos en lenguaje natural, con el fin de identificar los nombres de los textos en el diccionario.

Esto suena como una aplicación para el Aho-Corasick algorithm: construir un autómata del diccionario (en tiempo lineal), que luego se pueden utilizar para encontrar todas las ocurrencias de cualquiera de las palabras del diccionario en varios textos (también en forma lineal hora).

(La descripción en these lecture notes, vinculado desde la sección "enlaces externos" de la página de Wikipedia, es mucho más fácil de leer que la descripción de la página en sí.)

4

¿Qué operaciones Qué tienes pensado hacer? libdivsufsort fue en un momento la mejor implementación de matriz de sufijos en C.

+0

¿Cuál es la técnica para lograr esa eficiencia para la construcción del conjunto de sufijos? – curious

+0

Pregunta oportuna. AmpLab acaba de lanzar una versión paralela con una explicación en profundidad, https://amplab.cs.berkeley.edu/publication/parallel-lightweight- wavelet-tree-suffix-array-and-fm-index-construction/ –

0

This implementación del algoritmo de ordenación inducida (llamado sais) tiene una versión de Java para construir matrices de sufijos.

1

Trie vs árbol de sufijos estructura

tanto los datos de garantizar un aspecto muy rápido hacia arriba, el tiempo de búsqueda es proporcional a la longitud de la palabra de consulta, tiempo de complejidad O (m) donde m es la longitud de la consulta palabra.

es decir si tenemos una palabra de consulta que tiene 10 caracteres, por lo que necesitamos como mucho 10 pasos para encontrarla.

Trie: Un árbol para almacenar cadenas en el que hay un nodo para cada prefijo común. Las cadenas se almacenan en nodos de hojas adicionales.

suffix tree: Representación compacta de un trie correspondiente a los sufijos de una cadena dada donde todos los nodos con un hijo se fusionan con sus padres.

def son de: Diccionario de Algoritmos y Estructuras de Datos

general Trie utiliza para términos de índice del diccionario (léxico) o cualquier conjuntos de cadenas ejemplo D = {ABCD, abcdd, bxcdf, ....., Zzzz}

un árbol sufijo usado un índice de texto utilizando la misma estructura de datos "Trie" en todos los sufijos de nuestro texto T = abcdabcg todos los sufijos de T = {abcdabcg, abcdabc, abcdab, abcda, ABCD, abc, ab, a}

ahora parece un grupo de cadenas. construimos un Trie sobre este grupo de cadenas (todos los sufijos de T).

la construcción de ambas estructuras de datos es lineal, toma O (n) en tiempo y espacio.

en caso de dicionario (un conjunto de cadenas): n = la suma de los caracteres de todas las palabras. en el texto: n = longitud del texto.

array de sufijo: es una técnica para representar un árbol de sufijo en sapce comprimido, es una matriz de todas las posiciones de inicio de los sufijos de una cadena.

es más lento que el árbol de sufijos en el tiempo de búsqueda.

para obtener más información, vaya a la wikipedia, hay un buen artículo que habla sobre este tema.