Rechercher dans un texte

Comment trouver un motif sans examiner tous les départs possibles ?

Environ 45 minutes

  • Exécuter une recherche naïve et une recherche par décalages.
  • Construire une table de Horspool.
  • Justifier les indices, les sauts et les cas limites.
Sommaire
  1. Définir exactement la recherche
  2. De la méthode naïve aux décalages
  3. Prétraiter le motif correctement
  4. Exécuter la recherche
  5. Au bac et validation du programme
  6. S’entraîner

Comment trouver un motif sans examiner tous les départs possibles ?

Une recherche textuelle vise une suite exacte de caractères dans un texte plus long. Nous partirons d’une méthode naïve, puis étudierons la variante de Horspool de la famille Boyer–Moore : elle compare de droite à gauche et prépare des décalages à partir du motif. Tu dois connaître les chaînes Python, leurs indices commençant à zéro et les dictionnaires. Les exemples utilisent des lettres majuscules sans traitement linguistique supplémentaire.

Définir exactement la recherche

Appelons texte la chaîne dans laquelle on cherche, motif la chaîne cherchée, n la longueur du texte et m celle du motif. Une occurrence à l’indice i signifie que les m caractères texte[i], …, texte[i + m − 1] sont respectivement égaux aux caractères du motif. Le dernier départ possible est n − m, inclus. Si m dépasse n, il n’existe aucun départ possible.

Le résultat peut être un booléen, l’indice de la première occurrence, ou la liste de toutes les occurrences. Ces contrats sont différents. Ici, on cherche d’abord la première occurrence et on renvoie −1 en cas d’absence. Pour un motif vide, nous choisissons explicitement la convention de renvoyer zéro. L’algorithme de décalage sera ensuite décrit pour un motif non vide.

La recherche exacte distingue les majuscules, les minuscules, les espaces et les accents. Chercher CHAT n’est pas chercher chat ni seulement un mot entier : un motif peut apparaître à l’intérieur d’un mot plus long. Un traitement qui ignore la casse ou limite les résultats aux mots entiers ajoute d’autres règles. Il faut les spécifier avant de choisir les tests, et garder la correspondance entre les indices si l’on transforme le texte.

Exemple résolu

Recherche naïvement le motif ABA dans ABABA et donne toutes les occurrences, y compris celles qui se chevauchent.

  1. Étape 1 : Le texte contient cinq caractères et le motif trois. Les départs possibles sont 0, 1 et 2.
  2. Étape 2 : Au départ 0, les caractères A, B, A correspondent : une occurrence est trouvée.
  3. Étape 3 : Au départ 1, le premier caractère du texte est B au lieu de A : ce départ échoue.
  4. Étape 4 : Au départ 2, les trois caractères A, B, A correspondent à nouveau.

Résultat : Les occurrences commencent aux indices 0 et 2. Elles partagent le caractère d’indice 2.

Piège à éviter : Avancer systématiquement de la longueur du motif après une réussite ferait manquer une occurrence chevauchante.

À toi d'essayer

Un texte a huit caractères et le motif en a trois. Quels indices de départ faut-il pouvoir examiner, et combien sont-ils ?

Voir la réponse

Les indices vont de 0 à 5 inclus, car 8 − 3 = 5. Il y a donc six départs possibles.

De la méthode naïve aux décalages

La méthode naïve essaie chaque départ de gauche à droite. Pour chaque fenêtre, elle compare les caractères du motif et du texte jusqu’à une différence ou jusqu’à la correspondance complète. Après un échec, elle avance d’une position. Elle est simple, mais elle répète parfois beaucoup de comparaisons. La borne évidente est m × (n − m + 1) comparaisons lorsque 1 ≤ m ≤ n.

Boyer–Moore exploite l’information obtenue pendant une comparaison pour éviter certains départs impossibles. La famille contient plusieurs variantes. La version présentée ici, dite de Horspool, utilise une table de décalages et le caractère du texte placé à l’extrémité droite de la fenêtre. Elle ne mélange pas cette règle avec celle du caractère rencontré à un autre endroit lors de l’échec.

Dans une fenêtre fixée, on compare le motif de droite à gauche. Le départ de la fenêtre, lui, progresse toujours vers la droite du texte. Le sens des comparaisons et le sens de déplacement sont donc deux notions distinctes. Si toutes les lettres correspondent, on a trouvé une occurrence. Sinon, la table indique de combien avancer la fenêtre, sans recommencer automatiquement au départ suivant.

Le dernier caractère de la fenêtre est H ; le décalage de Horspool vaut 2.

Pour le motif CHAT de longueur quatre, la dernière case est T. On construit la table à partir de toutes les autres positions. C est à trois places du bord droit, H à deux places et A à une place. Tout caractère absent de cette partie du motif reçoit le décalage quatre. La table est donc C : 3 ; H : 2 ; A : 1 ; autres caractères : 4, y compris T dans ce motif.

Prétraiter le motif correctement

Construire la table de Horspool

  1. Pour un motif non vide de longueur m, choisir m comme décalage par défaut pour les caractères absents.
  2. Parcourir les indices j de 0 à m − 2, donc sans le dernier caractère. Affecter au caractère motif[j] le décalage m − 1 − j.
  3. Si un caractère apparaît plusieurs fois, l’affectation la plus à droite remplace les précédentes. Elle donne le plus petit décalage compatible avec sa présence.
  4. Pendant la recherche, lire la table avec texte[i + m − 1], le caractère situé au bord droit de la fenêtre actuelle.

Pourquoi exclure la dernière case du motif ? Sa distance au bord droit est zéro. L’utiliser créerait un décalage nul pour ce caractère et pourrait bloquer la progression. En excluant cette case, tous les décalages construits sont strictement positifs. La recherche avance donc et finit par dépasser le dernier départ possible si elle ne trouve pas de correspondance.

Exemple résolu

Construis la table du motif ABACA de longueur cinq.

  1. Étape 1 : Le décalage par défaut est 5. On parcourt seulement les indices 0, 1, 2 et 3.
  2. Étape 2 : À l’indice 0, A reçoit 4 ; à l’indice 1, B reçoit 3.
  3. Étape 3 : À l’indice 2, A reçoit 2, ce qui remplace sa première valeur. À l’indice 3, C reçoit 1.
  4. Étape 4 : Le A de l’indice 4 n’est pas traité, car il est dans la dernière case.

Résultat : La table donne A : 2 ; B : 3 ; C : 1 ; tout autre caractère : 5.

Piège à éviter : Garder la première occurrence de A au lieu de la dernière occurrence avant le bord droit pourrait sauter une position utile.

Le décalage est sûr car le caractère placé au bord droit doit être aligné avec une occurrence compatible dans le motif si une nouvelle correspondance le recouvre. On choisit l’occurrence la plus à droite avant la dernière case. Les décalages plus petits aligneraient ce caractère avec des positions où il est absent. S’il n’apparaît nulle part dans cette partie, on peut avancer de m positions. Cette explication concerne cette variante précise, pas n’importe quelle formule de saut.

À toi d'essayer

Pour le motif AAAA, quel décalage la table attribue-t-elle à A ? Qu’en déduis-tu sur l’affirmation « cette méthode saute toujours plusieurs caractères » ?

Correction détaillée pas à pasDans ce chapitre : 2 corrections détaillées.

Exécuter la recherche

Exemple résolu

Cherche la première occurrence de CHAT dans UNCHAT avec la table de Horspool.

  1. Étape 1 : Au départ i = 0, la fenêtre contient UNCH. Comparer depuis la droite : le T du motif diffère du H du texte.
  2. Étape 2 : Le caractère au bord droit de la fenêtre est H. Sa table donne un décalage de 2 : le nouveau départ vaut i = 2.
  3. Étape 3 : La fenêtre contient maintenant CHAT. Comparer T avec T, puis A avec A, H avec H et C avec C : tout correspond.

Résultat : La première occurrence commence à l’indice 2. Cinq comparaisons ont été effectuées : une sur la première fenêtre, puis quatre sur la seconde.

Piège à éviter : Renvoyer l’indice 5 du dernier caractère comparé confond le bord de la fenêtre avec le départ du motif.

Après le décalage, les quatre comparaisons réussissent ; l’occurrence commence à l’indice 2.

Pour programmer, garder deux indices de rôles différents : i repère le début de la fenêtre dans le texte, j repère la position comparée dans le motif. À chaque nouvelle fenêtre, remettre j à m − 1. Tant que j est positif ou nul et que les deux caractères correspondent, diminuer j. Lorsque j devient négatif, la correspondance est complète. Sinon, augmenter i selon la table avant de recommencer.

La condition de boucle sur les fenêtres est i + m ≤ n. Elle autorise une occurrence qui se termine exactement au dernier caractère du texte. Le test j ≥ 0 doit précéder l’accès aux caractères pour ne pas laisser les indices négatifs de Python comparer involontairement la fin des chaînes. Une trace écrite montre rapidement ces erreurs de frontière.

À toi d'essayer

Un programme décale la fenêtre d’après le caractère qui a provoqué l’échec, même si cet échec se produit au milieu du motif, mais conserve la table de Horspool. Peut-on lui faire confiance sans autre justification ?

Correction détaillée pas à pasDans ce chapitre : 2 corrections détaillées.

Au bac et validation du programme

Au bac : rendre une trace vérifiable

  1. Écrire les indices du texte et du motif, puis annoncer la variante utilisée et la convention de résultat.
  2. Construire la table avant la recherche. Vérifier les lettres répétées et l’exclusion de la dernière position.
  3. Pour chaque fenêtre, noter son départ, les comparaisons de droite à gauche, le caractère de référence du décalage et le saut appliqué.
  4. Conclure par un indice de départ ou par l’absence de motif. Vérifier séparément les cas limites.

Les tests doivent inclure un motif absent, un motif plus long que le texte, une occurrence au début, une à la fin, des lettres répétées et un texte vide. Pour la convention du motif vide, vérifier explicitement le résultat zéro. Sur de petites chaînes, on peut comparer systématiquement sa fonction à une recherche naïve indépendante ou à str.find. Une égalité sur beaucoup de cas détecte des erreurs ; la sûreté des sauts reste expliquée par le raisonnement.

Le prétraitement se fait une fois par motif, puis sert à toutes les fenêtres de la recherche. Son intérêt augmente lorsqu’un même motif est cherché dans de grands textes. On ne prétend pas que cette méthode est toujours plus rapide pour toutes les entrées. Le programme de terminale privilégie la compréhension des comparaisons et du prétraitement ; une analyse complète du coût de Boyer–Moore n’est pas exigée.

Attention :

Erreurs fréquentes : oublier le dernier départ possible ; donner un décalage nul ; confondre indice du motif et indice du texte ; ignorer les occurrences chevauchantes dans un comptage ; utiliser une table avec la mauvaise règle de décalage.

Vocabulaire

Motif :
Suite de caractères dont on cherche une occurrence.
Fenêtre :
Partie du texte de même longueur que le motif, située à un départ donné.
Prétraitement :
Calcul effectué sur le motif avant de parcourir le texte.
Occurrence :
Correspondance complète du motif à une position du texte.

Bilan

RepèreSens
NaïfTous les départs, avance d’une position.
HorspoolComparaison depuis la droite, table calculée sur le motif.
ContratPremière occurrence et −1 en cas d’absence, convention explicite pour le motif vide.

S’entraîner

Pour poursuivre ton entraînement, ouvre la rubrique S’entraîner du site, à l’adresse /exercices. Reprends d’abord les questions de cette leçon sans afficher les réponses, puis compare ton raisonnement à la correction.

À retenir

  • Les indices des chaînes commencent à zéro.
  • Le dernier départ possible est n − m, inclus.
  • Horspool compare de droite à gauche et déplace la fenêtre vers la droite.
  • La table présentée exclut la dernière position du motif.

Fiche de révision

Pour un motif de longueur m, préparer un saut m par défaut et remplacer par les distances au bord droit des positions 0 à m − 2.

Pendant une fenêtre, garder séparés i, début dans le texte, et j, position dans le motif.

Le caractère utilisé par cette table est toujours celui du bord droit de la fenêtre, même si l’échec survient ailleurs.

Un comptage de toutes les occurrences doit prévoir le chevauchement ; ABABA contient deux occurrences de ABA.

Et maintenant ?

Tu as lu le cours. L’étape suivante tient en une action.

Relis le coursReprends l’essentiel avant de passer à la suite.

Prolonge l’expérience !

Continue à explorer ce chapitre à travers de nouvelles activités, des défis et des expériences interactives. Avec Premium, l’apprentissage continue !

Ici, tu débloques aussi 2 corrections détaillées.

Parent ? Suivez les progrès de votre enfant.

Tous les cours de NSI