2010-06-28 11 views
5

Estoy tratando de evaluar diferentes algoritmos e implementaciones de búsqueda de subcadenas (ala strstr) y buscando algunas cadenas de agujas y pajar bien diseñadas que capten el peor de los casos y posibles errores en las esquinas. Supongo que podría resolverlos yo mismo, pero creo que alguien tiene que tener una buena colección de casos de prueba sentados en algún lugar ...¿Cuáles son los buenos casos de prueba para los algoritmos de búsqueda de subcadenas de benchmarking y stress testing?

+2

¿Cuál es su objetivo final aquí? ¿Solo para aprender sobre los algoritmos? ¿O tienes una aplicación con agujas/pajares inusuales? – Cascabel

+0

En el corto plazo, solo para aprender sobre los algoritmos. A largo plazo, tengo una implementación de biblioteca C orientada hacia un tamaño muy pequeño con un rendimiento superior al promedio que usa el enfoque ingenuo de strstr, y me gustaría considerar reemplazarlo con uno de los O (n) tiempo/O (1) algoritmos espaciales. SMOA parece prometedor, pero quiero ver si el constante 6 en el límite superior 6n + 5 en las comparaciones es problemático en la práctica (mis pruebas iniciales muestran que es mucho más bajo en datos de manera remota y comparable en rendimiento a glibc sin todas las especialidades). carcasa para agujas cortas/largas). –

Respuesta

0

No responde su pregunta directamente, pero puede encontrar los algoritmos en el libro - Algoritmos en cadenas, árboles y secuencias: informática y biología computacional: interesante (tiene muchos algoritmos novedosos para la búsqueda de subcadenas). Además, también es una buena fuente de casos especiales y complejos.

+0

Gracias, pero es realmente ideas de prueba/evaluación comparativa que estoy buscando. Tengo una referencia decente en algoritmos aquí: http://www-igm.univ-mlv.fr/~lecroq/string/index.html Two Way y SMOA parecen ser las únicas "rápidas" (en big-O) Algoritmos adecuados para el código que no tiene permitido tener casos de falla, ya que el resto no son constantes en el espacio y podrían fallar bajo condiciones de memoria estresada. Sin embargo, la implementación ingenua también es muy interesante y parece que puede ser óptima hasta tamaños de aguja extremadamente grandes. Es aproximadamente el doble de rápido que el Two Way de glibc para cuerdas cortas a moderadas que he probado. –

+0

¡Gracias por el enlace! esa es una buena compilación de algoritmos exactos de coincidencia de cadenas. – tathagata

3

Algunos pensamientos y una respuesta parcial a mí mismo:

peor de los casos para el algoritmo de fuerza bruta:

a^(n+1) b en (a^n b)^m

por ejemplo, aaab en aabaabaabaabaabaabaab

peor caso para SMOA:

Algo así como yxyxyxxyxyxyxx en (yxyxyxxyxyxyxy)^n. Necesita mayor refinamiento. Estoy tratando de asegurar que cada avance sea solo la mitad de la duración de la coincidencia parcial, y que el cálculo del sufijo máximo requiera la máxima cantidad de retroceso. Estoy bastante seguro de que estoy en el camino correcto porque este tipo de caso es la única forma que he encontrado hasta ahora para hacer que mi implementación de SMOA (que es asintóticamente 6n+5) funcione más despacio que glibc's Two-Way (que es asintóticamente) 2n-m pero tiene una sobrecarga de preprocesamiento moderadamente dolorosa).

peor de los casos para cualquier cosa rodadura-hash basado:

Cualquiera que sea la secuencia de bytes provoca colisiones hash con el hash de la aguja. Para cualquier hash razonablemente rápido y una aguja dada, debería ser fácil construir un pajar cuyo hash colisiona con el hash de la aguja en cada punto. Sin embargo, parece difícil crear simultáneamente coincidencias parciales largas, que son la única forma de obtener el peor de los casos. Naturalmente, para el peor de los casos, la aguja debe tener cierta periodicidad y una forma de emular el hash ajustando solo los caracteres finales.

peor de los casos de dos vías:

parece ser muy corto aguja con la descomposición de MS no trivial - algo así como bac - donde el pajar contiene repetidas falsos positivos en el componente de la mitad derecha de la aguja - algo así como dacdacdacdacdacdacdac . La única forma en que este algoritmo puede ser lento (aparte de que los autores de glibc lo implementan de forma deficiente ...) es haciendo que el bucle externo itere muchas veces e incurra repetidamente en esa sobrecarga (y haciendo que la sobrecarga de configuración sea significativa).

Otros algoritmos:

estoy muy interesado sólo en algoritmos que son O(1) en el espacio y tienen una baja sobrecarga de procesamiento previo, por lo que no han mirado sus peores casos tanto. Al menos Boyer-Moore (sin las modificaciones para que sea O(n)) tiene un peor caso no trivial donde se convierte en O(nm).

0

Un procedimiento que podría dar estadísticas interesantes, aunque no tengo tiempo para probar en este momento:

Selección aleatoria sobre longitud de la cadena, continuación RANDOMIZE sobre contenidos de la cadena de esa longitud, continuación RANDOMIZE sobre desplazamiento/longitud de una substring (posiblemente algo que no está en la cadena), y luego aleatoriamente clobber sobre la subcadena (posiblemente nada), repeat.

0

Puede generar cadenas de contenedores (Resp., Contenía valores de prueba) de forma recursiva por:

Comenzando con la cadena vacía, generar todas las secuencias dadas por el aumento de una cadena actualmente en el conjunto mediante la adición de un personaje de una alfabeto a la izquierda o a la derecha (ambos).

El alfabeto para generar cadenas de contenedor es elegido por usted.

Prueba 2 alfabetos para cadenas contenidas. Uno es el que compone cadenas de contenedores, el otro es su complemento.

Cuestiones relacionadas