En informática, el algoritmo Raita es un algoritmo de búsqueda de cadenas que mejora el rendimiento del algoritmo Boyer–Moore–Horspool . Este algoritmo preprocesa la cadena que se busca en busca del patrón, lo que es similar al algoritmo de búsqueda de cadenas Boyer–Moore . El patrón de búsqueda de una subcadena particular en una cadena dada es diferente del algoritmo Boyer–Moore–Horspool. Este algoritmo fue publicado por Timo Raita en 1991. [1]
El algoritmo Raita busca un patrón "P" en un texto "T" determinado comparando cada carácter del patrón en el texto determinado. La búsqueda se realizará de la siguiente manera. La ventana para un texto "T" se define como la longitud de "P".
Si todo en la comprobación previa es correcto, entonces la comparación original comienza desde el segundo carácter hasta el penúltimo. Si hay una discrepancia en cualquier etapa del algoritmo, se ejecuta la función de desplazamiento de caracteres incorrectos que se calculó en la fase de preprocesamiento. La función de desplazamiento de caracteres incorrectos es idéntica a la propuesta en el algoritmo de Boyer–Moore–Horspool. [1]
Una formulación moderna de una comprobación previa similar se encuentra en std::string::find
, un comparador de cadenas lineal/cuadrático, en libc++ y libstdc++. Suponiendo una versión bien optimizada de memcmp
, no omitir caracteres en la "comparación original" tiende a ser más eficiente ya que es probable que el patrón esté alineado. [2]
#include <limites.h> #include <stddef.h> #define ALPHABET_SIZE (1 << CHAR_BITS) /* normalmente 256 *//* Preprocesamiento: la tabla de coincidencias incorrectas de BMH. */ static inline void preBmBc ( char * pat , size_t lpat , ptrdiff_t bmBc []) { size_t i ; for ( i = 0 ; i < ALPHABET_SIZE ; ++ i ) bmBc [ i ] = lpat ; for ( i = 0 ; i < lpat - 1 ; ++ i ) bmBc [ pat [ i ]] = lpat - i - 1 ; } void RAITA ( char * pat , tamaño_t lpat , char * s , tamaño_t n ) { ptrdiff_t bmBc [ TAMAÑO_ALFABETO ]; /* Casos extremos rápidos. */ if ( lpat == 0 || lpat > n ) return ; si ( lpat == 1 ) { char * match_ptr = s ; mientras ( match_ptr < s + n ) { match_ptr = memchr ( match_ptr , pat [ 0 ], n - ( match_ptr - s )); si ( match_ptr != NULL ) { SALIDA ( match_ptr - s ); match_ptr ++ ; } de lo contrario devolver ; } } preBmBc ( palmadita , lpat , bmBc ); /* La ventana previa al partido. */ char firstCh = pat [ 0 ]; char middleCh = palmadita [ lpat / 2 ]; char lastCh = palmadita [ lpat - 1 ]; /* Búsqueda */ ptrdiff_t j = 0 ; while ( j <= n - m ) { char c = s [ j + lpat - 1 ]; /* Esto podría dañar la localidad de los datos en patrones largos. Para estos, considere reducir * la cantidad de pruebas previas o usar índices más agrupados. */ if ( lastCh == c && middleCh == s [ j + lpat / 2 ] && firstCh == s [ j ] && memcmp ( & pat [ 1 ], & s [ j + 1 ], lpat - 2 ) == 0 ) OUTPUT ( j ); j += bmBc [ c ]; } }
Patrón: abddb
Texto:abbaabaabddbabadbb
Etapa de preprocesamiento:
desde 4 3 1
Intento 1: abbaabaabddbabadbb ....b Desplazamiento por 4 (bmBc[a])
Comparación del último carácter del patrón con el carácter más a la derecha de la ventana. No coincide y se desplaza en 4 puntos según el valor de la etapa de preprocesamiento.
Intento 2: abbaabaabddbabadbb AdB Desplazamiento por 3 (bmBc[b])
Aquí, el último y el primer carácter del patrón coinciden, pero el carácter del medio no coincide, por lo que el patrón cambia según la etapa de preprocesamiento.
Intento 3: abbaabaabddbabadbb ABDDB Desplazamiento por 3 (bmBc[b])
Encontramos una coincidencia exacta aquí, pero el algoritmo continúa hasta que no puede avanzar más.
Intento 4: abbaabaABDDBabadbb ....b Desplazamiento por 4 (bmBc[a])
En esta etapa, necesitamos desplazarnos 4 veces y no podemos mover el patrón 4 veces. Por lo tanto, el algoritmo finaliza. Las letras en mayúsculas son exactamente iguales al patrón del texto.