Algorithme de Boyer-Moore-Horspool

L'algorithme de Boyer-Moore-Horspool ou Horspool est un algorithme de recherche de sous-chaîne publié par Nigel Horspool en 1980.

Il consiste en une simplification de l’algorithme de Boyer-Moore qui ne garde que la première table de saut.

On notera T le texte de recherche, P la sous-chaîne recherchée et ∑ l'alphabet.

Description

L'algorithme utilise un pré-traitement de P afin de calculer le saut maximum à effectuer après avoir trouvé une non-concordance. Durant la recherche la comparaison se fait de la droite vers la gauche.

Exemple

Si P="string" et que le texte est T="wikipedia" :

  • à la première occurrence, le dernier caractère de P est comparé à sa position dans T, soit 'g' vs 'e'. On cherche la valeur de 'e' dans la table de saut, et comme 'e' n'existe pas dans P la valeur retournée est |P|, soit 6.
  • à la seconde occurrence, le curseur est déplacé de 6 et déborde de T, la recherche s'arrete ici et P n'a pas été trouvé dans T

Ce cas extrême est intéressant car un seul caractère de T a été lu.

Complexité

En espace, Horspool a une complexité O(|∑|).

Le pré-traitement a une complexité en temps en O(|P|+|∑|).

La recherche a une complexité en temps en O(|T|*|P|) dans les cas pathologiques et en O(|T|) en moyenne.

Implémentation

Exemple d'implémentation en C.

#define ALPHABET_SIZE   256     // taille de l'alphabet ASCII

/**
 * Implémentation de Boyer-Moore-Horspool
 *
 * Note : retourne directement la position du premier pattern trouvé dans text, sinon -1
 */
int bmh(char *text, char *pattern)
{
        unsigned int skip_table[ALPHABET_SIZE];
        ssize_t tsize, psize;
        int i;

        tsize = strlen(text);
        psize = strlen(pattern);

        /* pré-traitement */
        /** remplir la table avec la valeur de saut maximum */
        for (i = 0; i < ALPHABET_SIZE; i++)
                skip_table[i] = psize;

        /** puis calculer pour chaque caractère de pattern le saut */
        for (i = 0; i < psize - 1; i++)
                skip_table[(int) pattern[i]] = psize - i - 1;

        /* recherche */
        i = 0;
        while (i <= tsize - psize) {
                if (text[i + psize - 1] == pattern[psize - 1])
                        if (memcmp(text + i, pattern, psize - 1) == 0)
                                return i;

                /* si les deux caractères comparés sont différents, 
                sauter en utilisant la valeur de la table de saut à
                l'index du caractère de text */
                i += skip_table[(int) text[i + psize - 1]];
        }

        return -1;
}
  • Portail de l'informatique théorique
Cet article est issu de Wikipedia. Le texte est sous licence Creative Commons - Attribution - Partage dans les Mêmes. Des conditions supplémentaires peuvent s'appliquer aux fichiers multimédias.