Terminale · Algorithmique

Recherche textuelle et algorithme de Boyer-Moore

Chercher un mot dans un texte ne demande pas toujours d’essayer chaque position avec le même travail. Boyer-Moore exploite les informations d’un échec de comparaison pour décaler le motif. Le prétraitement du motif prépare ces décisions avant de parcourir le texte.

SofienAvec SofienIngénieur et enseignant en informatique
Dans ce chapitre

Un cap pour ce chapitre

Ce que vous saurez faire

  • Suivre des alignements de motif.
  • Construire une table de dernière occurrence.
  • Justifier un décalage de la règle du mauvais caractère.
Les bases utiles pour commencer

Définir une occurrence et ses indices

Le texte contient n caractères et le motif m caractères. Un alignement à l’indice s compare motif[j] à texte[s+j]. Si toutes les comparaisons correspondent, le motif apparaît à la position s. Les indices commencent ici à zéro, et la casse est significative.

La recherche naïve essaie les positions possibles puis compare les caractères, souvent de gauche à droite. Elle constitue une bonne référence de correction. Une recherche plus élaborée doit trouver les mêmes occurrences, y compris celles qui se chevauchent. Dans ABABA, ABA apparaît aux indices zéro et deux.

L’atelier compte des caractères Unicode par points de code, comme l’indexation usuelle d’une chaîne Python, et non les octets d’un fichier. Ainsi deux symboles 🐍 occupent ici deux positions. Des formes composées d’accents peuvent toutefois utiliser plusieurs points de code ; aucune normalisation linguistique n’est effectuée.

Comparer depuis la droite du motif

La famille Boyer-Moore compare le motif depuis sa droite. Lorsqu’un caractère différent est rencontré, on exploite cette différence pour avancer davantage qu’une seule position lorsque cela est justifié. Les caractères déjà comparés à droite peuvent également fournir des informations dans la version complète.

Cette page étudie explicitement une variante pédagogique utilisant seulement la règle du mauvais caractère avec une table de dernière occurrence. L’algorithme complet combine notamment cette règle à celle du bon suffixe. Les variantes n’ont pas exactement les mêmes décalages ; il faut appliquer les règles de l’énoncé plutôt que mélanger deux versions.

Prétraiter la dernière position de chaque caractère

Pour le motif ABCA, les dernières positions sont A:3, B:1 et C:2. Un caractère absent reçoit conceptuellement la position -1. En cas d’échec à la position j du motif contre le caractère c du texte, notre décalage vaut max(1, j-derniere(c)).

Si c est absent, le décalage j+1 dépasse sa position : aucun caractère du motif ne pourrait lui correspondre dans les alignements sautés. Si sa dernière occurrence est à gauche de j, on l’aligne sur c. Si cette occurrence est à droite de j, la formule peut être nulle ou négative ; le maximum avec un garantit une progression prudente.

Garder une correction vérifiable

Pour trouver toutes les occurrences, l’atelier avance d’une position après une correspondance complète. Ce choix volontairement prudent conserve les chevauchements. Pour une recherche de première occurrence seulement, on pourrait s’arrêter immédiatement. Si le motif est plus long que le texte, aucun alignement complet n’est possible.

Le motif vide demande une convention particulière ; ici l’atelier exige un motif non vide et le signale. Le programme de NSI demande de comprendre l’intérêt du prétraitement et le fonctionnement de Boyer-Moore. L’analyse détaillée de son coût est difficile et n’est pas exigible. On peut mesurer des comparaisons sur des exemples sans transformer ces observations en garantie générale non démontrée.

Ce programme complet suit exactement la variante annoncée et renvoie tous les débuts d’occurrence. Il rejette le motif vide, conserve la casse et utilise les indices des chaînes Python. Comparez ses résultats à la recherche naïve sur de petits textes.

def occurrences(texte, motif):
    if len(motif) == 0:
        raise ValueError("Le motif doit être non vide")
    derniere = {}
    for j, caractere in enumerate(motif):
        derniere[caractere] = j
    resultat = []
    debut = 0
    while debut <= len(texte) - len(motif):
        j = len(motif) - 1
        while j >= 0 and motif[j] == texte[debut + j]:
            j -= 1
        if j < 0:
            resultat.append(debut)
            debut += 1
        else:
            caractere = texte[debut + j]
            debut += max(1, j - derniere.get(caractere, -1))
    return resultat

assert occurrences("ABABA", "ABA") == [0, 2]
assert occurrences("AB", "ABC") == []

Exemple suivi : calculer deux décalages contrastés

Le motif ABCA possède A:3, B:1, C:2. Dans le texte ZZZABCA, le premier alignement commence en zéro. Depuis la droite, A du motif correspond à A du texte à l’indice 3 ; la comparaison suivante oppose C à Z à l’indice 2 et échoue. On a j=2 et dernière(Z)=-1 : le pas vaut trois. Le nouvel alignement commence donc en 3 et les quatre caractères correspondent.

Le décalage n’était pas quatre, car l’échec ne se produisait pas sur le dernier caractère du motif. La règle dépend de la position j de l’échec. Dans un autre alignement, si j=1 et le caractère rencontré est A, la différence 1-3 est négative ; on avance seulement de un. Appliquer systématiquement la longueur du motif ou la position du dernier caractère mélangerait des règles différentes et pourrait sauter une occurrence.

Exemple suivi : préparer un oracle et les cas limites

Un oracle naïf peut examiner chaque début s entre zéro et n-m, puis vérifier tous les caractères du motif. Sur ABABA avec ABA, il trouve 0 et 2. Sur AAAA avec AA, il trouve 0,1,2 : les occurrences se chevauchent. Une variante accélérée doit donner la même liste finale, même si ses comparaisons et ses décalages diffèrent. Le prétraitement change la manière de chercher, pas la définition d’une occurrence.

Si m dépasse n, l’ensemble des débuts possibles est vide et aucune comparaison n’est nécessaire. Si le texte est vide et le motif non vide, la conclusion est identique. Le motif vide demande un contrat différent et est refusé dans l’atelier. Testez aussi une différence de casse et des répétitions dans le motif : une table qui conserve la première occurrence au lieu de la dernière n’applique plus la formule annoncée. Les textes courts permettent de vérifier les sauts à la main avant toute mesure de performance.

À vous de faire varier les choses

Pilotez les alignements du motif

Entrez un texte court et un motif non vide, puis avancez d’alignement en alignement. Les majuscules et minuscules sont distinctes. Le texte est limité à 60 caractères et le motif à 12 ; les éventuels caractères suivants ne participent pas à cette simulation.

Lire le résultat de l’expérience initiale

Alignement 0 : échec, décalage 3.

Table de dernière occurrence : A:3, B:1, C:2. Après une réussite, le pas de un conserve les chevauchements.

Indice texteCaractère texteIndice motifCaractère motifComparaison
3A3AÉgal
2Z2CDifférent

Le prétraitement permet de sauter des alignements impossibles, à condition de justifier exactement la règle employée.

De la compréhension à l’autonomie

À vous de résoudre

Cherchez d’abord par vous-même. Vérifiez les résultats demandés, utilisez les indices si nécessaire, puis comparez votre méthode à la correction.

Exercice 1 · Appliquer#

Construire une table

Donnez la dernière position de chaque caractère du motif BANANE, avec indices à partir de zéro. Quelle valeur conventionnelle prend Z ?

Indice 1

Écrivez les indices sous les six lettres.

Indice 2

Une répétition remplace la position précédente dans la table.

Comprendre la correction

Les positions sont B:0, A:3, N:4 et E:5. Z est absent, donc sa position conventionnelle vaut -1. A apparaît aussi en un et N en deux, mais la table conserve leur occurrence la plus à droite.

Exercice 2 · Appliquer#

Calculer un décalage

Le motif ABCA échoue à j=3 contre Z. Calculez le décalage de la variante étudiée.

Indice 1

Z est absent du motif.

Indice 2

Remplacez derniere(Z) par -1.

Comprendre la correction

Le décalage vaut max(1,3-(-1))=4. Aucun caractère du motif ne peut correspondre à Z ; les alignements qui placeraient encore une partie du motif sur cette position ne peuvent pas réussir.

Exercice 3 · Corriger#

Éviter une progression nulle

Avec le motif ABCA, un échec à j=1 rencontre A. Pourquoi ne doit-on pas avancer de j-derniere(A) sans précaution ?

Indice 1

La dernière position de A vaut trois.

Indice 2

Un décalage négatif ne fait pas avancer la recherche.

Comprendre la correction

Le calcul brut donne 1-3=-2. La règle utilise max(1,-2)=1 pour garantir la progression. L’occurrence la plus à droite n’est pas exploitable pour ce décalage ; la variante adopte donc un déplacement sûr d’une position.

Exercice 4 · Justifier#

Conserver les chevauchements

Dans ABABA, le motif ABA est trouvé en zéro. Pourquoi avancer systématiquement de la longueur trois après cette réussite ferait-il manquer une occurrence ?

Indice 1

Cherchez le début suivant possible.

Indice 2

Deux occurrences peuvent partager des caractères.

Comprendre la correction

Une autre occurrence commence à l’indice deux. Avancer directement à trois la sauterait. Le choix d’un décalage après réussite doit donc préserver les chevauchements lorsque toutes les occurrences sont recherchées. Notre atelier utilise un pas de un dans ce cas.

Exercice 5 · Problème de synthèse#

Problème : suivre un échec intérieur

Cherchez ABCA dans ZZZABCA avec la règle enseignée. Détaillez les comparaisons du premier alignement de droite à gauche, le décalage et le résultat du suivant. Donnez le total de comparaisons de caractères pour ces deux alignements.

Indice 1

Le dernier A correspond avant l’échec contre Z.

Indice 2

Le deuxième alignement réussit sur quatre caractères.

Comprendre la correction

Au début zéro, A=A puis C≠Z : deux comparaisons, échec en j=2. Z absent donne un pas 2-(-1)=3. À s=3, A=A, C=C, B=B et A=A : quatre comparaisons et occurrence en 3. Les deux alignements totalisent six comparaisons. Le décalage utilise j à l’échec, pas automatiquement m.

Exercice 6 · Problème de synthèse#

Problème : conserver toutes les occurrences

Pour le texte AAAA et le motif AA, construisez la table de dernière occurrence puis donnez tous les alignements réussis. Combien de comparaisons effectue la variante du cours ? Que perdrait une avance de deux après chaque réussite ?

Indice 1

La dernière position de A dans le motif vaut un.

Indice 2

Les débuts complets possibles sont 0,1,2.

Comprendre la correction

La table est A:1. Les occurrences commencent en 0,1,2 et chacune demande deux comparaisons, soit six. Une avance de deux après la première réussite passerait directement à 2 et manquerait celle de début 1. Le pas prudent de un protège les chevauchements ; il ne vise pas ici le meilleur décalage théorique après réussite.

Exercice 7 · Problème de synthèse#

Problème : auditer une table et les frontières

Un programme traite BANANE avec la table B:0, A:1, N:2, E:5. Corrigez-la et calculez le décalage pour un échec en j=4 contre A. Donnez ensuite le résultat attendu pour un texte AB et motif ABC, puis pour texte 🐍A🐍 et motif 🐍 dans la convention de l’atelier.

Indice 1

Les répétitions remplacent les positions précédentes.

Indice 2

Les indices du texte portent sur les caractères représentés.

Comprendre la correction

La table correcte est B:0, A:3, N:4, E:5. Le décalage demandé vaut max(1,4-3)=1. Avec AB et ABC, aucun alignement complet n’existe et le compte de comparaisons vaut zéro. Avec 🐍A🐍 et 🐍, les occurrences sont 0 et 2. La convention Unicode évite de confondre position de caractère et unité d’encodage.

Les erreurs qui méritent un détour

Mélanger les tables de deux variantes.
La règle du mauvais caractère et les variantes de décalage doivent être annoncées précisément.
Prendre une mesure sur un texte comme preuve de coût général.
Le comportement varie selon texte et motif ; la correction des sauts reste prioritaire.

La fiche à garder

L’essentiel à retenir

  • Le motif est comparé de droite à gauche.
  • Le prétraitement guide des décalages justifiés.
  • La variante étudiée utilise max(1,j-derniere(c)) après un échec.

Cette notion au bac

Retrouvez ces idées dans un sujet complet, avec des indices, une correction expliquée et des ateliers.

Le prochain pas

Retrouver le catalogue de Terminale

Ce chapitre s’appuie sur le programme officiel de Terminale (PDF, nouvel onglet). Les explications et exercices sont proposés pour l’apprentissage.