Exercice 1 : Recherche de motifs (algorithmes KMP et Boyer-Moore)
🌐 Énoncé du problème / Cadre d’étude
Section titled “🌐 Énoncé du problème / Cadre d’étude”La recherche efficace de motifs dans une chaîne de caractères est un enjeu fondamental en informatique, intervenant dans l’analyse de séquences génomiques, le traitement du langage naturel ou encore la recherche textuelle (fonctionnalité “Rechercher” des éditeurs).
Soit un texte de longueur et un motif de longueur , tous deux construits sur un alphabet fini de taille . On suppose généralement . L’objectif est de trouver toutes les occurrences de dans , c’est-à-dire l’ensemble des indices tels que pour tout , .
Dans ce problème, nous étudions deux algorithmes de pointe permettant d’améliorer la complexité naïve en :
- L’algorithme de Knuth-Morris-Pratt (KMP), qui exploite les redondances au sein du motif pour éviter de reculer dans le texte lors d’une mismoyenne.
- L’algorithme de Boyer-Moore (version Boyer-Moore-Horspool ou règle du mauvais caractère), qui parcourt le motif de droite à gauche et permet de sauter des portions entières du texte.
❓ Questions progressives (incluant une analyse critique du modèle)
Section titled “❓ Questions progressives (incluant une analyse critique du modèle)”Partie I : L’algorithme de Knuth-Morris-Pratt (KMP)
Section titled “Partie I : L’algorithme de Knuth-Morris-Pratt (KMP)”-
Définition de la table de préfixes (ou tableau ) Soit le motif de longueur . On définit la fonction (souvent appelée tableau next ou pi) sur l’ensemble telle que est la longueur du plus grand préfixe propre de qui est aussi un suffixe de .
- Rédiger la spécification formelle de .
- Calculer à la main le tableau pour le motif .
-
Utilisation de la table pour la recherche Expliquer comment, lors d’une divergence entre et , l’utilisation de permet de reprendre la comparaison sans réexaminer les caractères de déjà validés.
-
Complexité temporelle de KMP
- Écrire la fonction de calcul de la table en langage Python.
- Démontrer par un argument d’amortissement (ou analyse du potentiel) que le calcul de la table s’effectue en temps et la recherche textuelle globale en temps .
Partie II : L’algorithme de Boyer-Moore (Règle du mauvais caractère)
Section titled “Partie II : L’algorithme de Boyer-Moore (Règle du mauvais caractère)”-
Principe de la règle du mauvais caractère On considère un parcours du motif de droite à gauche ( allant de à ). Supposons que (mauvais caractère à l’indice du motif, correspondant au caractère dans le texte).
- Si apparaît dans à des indices inférieurs à , de combien de positions peut-on décaler le motif vers la droite pour aligner la dernière occurrence de dans avec ?
- Si n’apparaît pas du tout dans , quel est le décalage maximal possible ?
-
Mise en œuvre et complexité
- Définir une structure de données (pré-calcul) permettant d’obtenir le dernier indice d’apparition d’un caractère de dans en temps .
- Quel est le pire des cas théorique de l’algorithme de Boyer-Moore complet (comportant la règle du bon suffixe et du mauvais caractère) ? Donnez un exemple de texte et de motif illustrant ce pire cas.
💡 Pistes & Indications méthodologiques
Section titled “💡 Pistes & Indications méthodologiques”- Pour la table (KMP) : Pensez à l’algorithme de construction par récurrence. Si l’on connait , on peut tester si . Attention aux rebonds successifs si l’égalité n’est pas vérifiée.
- Amortissement KMP : Pour prouver la complexité linéaire, définissez un potentiel lié à l’indice de lecture du texte et à l’indice dans le motif . Montrez que chaque opération élémentaire incrémente strictement une grandeur bornée ou consomme du potentiel.
- Boyer-Moore : Le pré-calcul de la table du mauvais caractère nécessite de parcourir le motif une seule fois. Attention à bien gérer les caractères de l’alphabet absents de (décalage de ).
📋 Corrigé détaillé pas à pas
Section titled “📋 Corrigé détaillé pas à pas”Partie I : KMP
Section titled “Partie I : KMP”-
Table des préfixes pour
- (pas de préfixe propre pour un seul caractère).
- Pour : aucun préfixe propre n’est suffixe .
- Pour : le préfixe est suffixe .
- Pour : le préfixe est suffixe .
- Pour : le préfixe est suffixe .
- Pour : aucun préfixe propre ne correspond à un suffixe se terminant par .
Résultat : .
-
Utilisation lors d’une divergence Si une divergence survient à l’indice du motif (), cela signifie que le sous-texte ] correspond exactement à . Le plus grand préfixe de qui est aussi un suffixe de a une longueur de . Par conséquent, on peut directement aligner ce préfixe avec la fin du segment textuel déjà reconnu, en reprenant les comparaisons à l’indice dans le texte et à l’indice dans le motif, sans jamais reculer l’indice du texte.
-
Implémentation et complexité de KMP
def calculer_pi(P): m = len(P) pi = [0] * m j = 0 for i in range(1, m): while j > 0 and P[i] != P[j]: j = pi[j - 1] if P[i] == P[j]: j += 1 pi[i] = j return pi
def kmp(T, P): n, m = len(T), len(P) if m == 0: return [] pi = calculer_pi(P) resultats = [] j = 0 for i in range(n): while j > 0 and T[i] != P[j]: j = pi[j - 1] if T[i] == P[j]: j += 1 if j == m: resultats.append(i - m + 1) j = pi[j - 1] # Pour trouver les occurrences suivantes potentiellement chevauchantes return resultats- Démonstration de la complexité linéaire :
Analysons la boucle principale de recherche. Soit le couple représentant la position dans et dans . À chaque tour de boucle, soit est incrémenté de (qu’il y ait correspondance ou non après les rebonds de ), soit diminue strictement lors des instructions
j = pi[j - 1]. Comme ne peut être incrémenté au total que fois (autant de fois que avance), et que chaque décrémentation de le rapproche de , le nombre total d’exécutions de la bouclewhileest borné linéairement par . Le calcul préalable de s’analysant de la même manière en , la complexité globale est .
Partie II : Boyer-Moore (Règle du mauvais caractère)
Section titled “Partie II : Boyer-Moore (Règle du mauvais caractère)”-
Principe de la règle du mauvais caractère Soit le caractère du texte provoquant une discordance avec lors d’un parcours de droite à gauche.
- Si apparaît dans à des indices strictement inférieurs à , soit le plus grand indice tel que (). Le décalage vers la droite du motif est de .
- Si n’apparaît pas dans , aucune occurrence de ne peut coïncider ; on décale le motif pour le positionner juste après l’indice , soit un décalage de (ou si ).
-
Structure de données et pire des cas
- Table des derniers indices : On utilise un tableau (ou une table de hachage) de taille (la taille de l’alphabet), noté
dernier[c], qui stocke pour chaque caractère l’indice de sa dernière apparition dans (ou s’il n’y figure pas). Sa construction s’effectue en par un simple parcours de . - Pire cas théorique : L’algorithme de Boyer-Moore (dans sa version complète) atteint un pire cas en comparaisons, par exemple lorsque et . À chaque tentative, le premier caractère testé (en partant de la droite) échoue, mais la règle du bon suffixe ou du mauvais caractère ne génère que des décalages minimes de position, conduisant à comparaisons pour chacun des décalages.
- Table des derniers indices : On utilise un tableau (ou une table de hachage) de taille (la taille de l’alphabet), noté