Physique-Chimie & NSI

Cours complets et originaux de Physique-Chimie & NSI

2-04. Recherche textuelle

La recherche d'un motif dans un texte consiste à localiser une séquence spécifique de caractères au sein d'un texte plus large. Cette technique est devenue cruciale en bioinformatique, où elle permet d'identifier des séquences génétiques spécifiques dans de vastes génomes, facilitant ainsi la découverte de gènes impliqués dans des maladies, l'analyse des mutations, et la compréhension de l'évolution des espèces.

Des algorithmes efficaces comme celui de Boyer-Moore sont essentiels pour effectuer ces recherches rapidement, car ils permettent d'analyser d'énormes volumes de données textuelles ou génomiques en un temps raisonnable, rendant possibles des avancées scientifiques qui auraient été impensables il y a quelques décennies.

Approche naïve

Imaginons le brin d’ADN avec la séquence de nucléotides suivante :

CAATCGCACAAGACGCGGCAGACCTTCGTTATAGGCGATGATTTCGAACCTACTAGTGGGTCTCTTAGGCCGAGCGGTTCCGAGAGATAGTGAAAGATGGCTGGGCTGTGAAGGGAAGGAGTCGTGAAAGCGCGAACACGAGTGTGCGCAAGCGCAGCGCCTTAGTATGCTCCAGTGTAGAAGCTCCGGCGTCCCGTCTAACCGTACGCTGTCCCCGGTACATGGAGCTAATAGGCTTTACTGCCCAATATGACCCCGCGCCGCGACAAAACAATAACAGTTTGCTGTATGTTCCATGGTGGCCAATCCGTCTCTTTTCGACAGCACGGCCAATTCTCCTAGGAAGCCAGCTCAATTTCAACGAAGTCGGCTGTTGAACAGCGAGGTATGGCGTCGGTGGCTCTATTAGTGGTGAGCGAATTGAAATTCGGTGGCCTTACTTGTACCACAGCGATCCCTTCCCACCATTCTTATGCGTCGTCTGTTACCTGGCTTGGCAT

Quel algorithme concevoir pour permettre de savoir si ce brin d'ADN contient une séquence donnée (par exemple ATATG), et si oui, en quelle position ?

Nous allons commencer par le premier algorithme qui nous vient à l'esprit (on parle souvent d'algorithme « naïf ») :

  • On examine chaque lettre du brin d’ADN. Si elle correspond à la première lettre du motif recherché (ici ATATG), alors, on compare la lettre suivante du brin avec la lettre suivante du motif, etc.
  • Si, à un moment les deux lettres comparées sont différentes, on décale l’analyse à la lettre suivante sur le brin.
  • On poursuit jusqu’à ce que le motif soit trouvé ou jusqu’à l’examen complet du brin.
Recherche « naïve » d’une séquence dans un texte 1 ATATG CAATCGCACAAGACGCGG… 2 ATATG CAATCGCACAAGACGCGG… 3 ATATG CAATCGCACAAGACGCGG… 4 ATATG CAATCGCACAAGACGCGG…
Recherche textuelle « naïve »

Cet algorithme naïf peut, selon les situations demander un très grand nombre de comparaisons, ce qui peut entraîner un très long temps de calcul avec des chaines très très longues. L'algorithme de Boyer-Moore, que l’on va voir au paragraphe suivant, permet de faire mieux en termes de comparaisons à effectuer

Recherche naïve

Proposer une implémentation de la fonction recherche_naive évoquée ci-dessus. Si le motif recherché est présent, la fonction doit renvoyer sa position. Sinon, elle doit renvoyer None.

Algorithme de Boyer-Moore

  • Étudier l’algorithme de Boyer-Moore pour la recherche d’un motif dans un texte.

L'algorithme de Boyer-Moore est un algorithme de recherche de motif particulièrement efficace, inventé en 1977. Celui qui est présenté ici, au programme de terminale, est en réalité une version simplifiée appelée algorithme de Boyer-Moore-Horspool

Algorithme de Boyer-Moore – Étape 1 A T A T G C A A T C G C A C A A G A C G
Étape 1

On commence par aligner le texte et le motif par le début, comme dans le cas de l’algorithme naïf. Mais on compare la dernière lettre du motif (G) avec celle du même rang dans le texte (C).
Ici, il n’y a pas de correspondance.

On cherche alors la première occurence de la lettre C (c’est-à-dire la lettre du texte qui a été comparée à la dernière lettre du motif) dans le motif, en parcourant le motif vers son début.
Ici, le motif ne contient pas cette lettre. On peut donc s’économiser toutes les comparaisons qui aligneraient une des lettres du motif avec ce C.

Algorithme de Boyer-Moore – comparaisons inutiles A T A T G C A A T C G C A C A A G A C G
Comparaisons inutiles

On peut donc décaler le motif d’un nombre de rang égal à sa longueur (ici 5).

Algorithme de Boyer-Moore – Étape 2.1 A T A T G C A A T C G C A C A A G A C G
Étape 2.1

Après décalage de 5 rangs, on constate que le G du motif ne correspond pas au A du texte. Cependant, A est présent dans le motif. Le premier A du motif se trouve après un décalage de 2 rangs. On décale donc le motif de 2 rangs pour effectuer une nouvelle comparaison.

Algorithme de Boyer-Moore – Étape 2.2 A T A T G C A A T C G C A C A A G A C G
Étape 2.2

On a maintenant une correspondance sur le G. Cependant, la lettre précédente du motif (T), ne correspond pas à la lettre du texte (A).

Algorithme de Boyer-Moore – Étape 3 A T A T G C A A T C G C A C A A G A C G
Étape 3

G n’étant pas présent ailleurs dans le motif, on décale le motif de 5 rangs vers la droite.

On continue comme ceci jusqu’à trouver le motif ou arriver à la fin du texte. Comme vous l’avez compris, cette méthode permet de réaliser moins de comparaisons que la méthode « naïve ». Elle est donc plus rapide. Elle est d’ailleurs d’autant plus efficace que le motif est long.

Animation de l’algorithme de Boyer-Moore

Merci à Erwan Demerville pour son animation

Implémentation de l’algorithme de Boyer-Moore

Grâce à l’animation ci-dessus, vous pouvez constater que le décalage du motif se fait grâce à une table de décalage.

1. Création de la table de décalage. Après avoir analysé, sur l’animation, comment la table de décalage est crée, compléter la fonction ci-dessous permettant de créer cette table.


			def creer_table_decalage(chaine):
				decalage = {}
				for i in range(...):
					...
				return decalage
		

Tester votre fonction grâce à la fonction ci-dessous :


			def test_creer_table_decalage():
				ctr = creer_table_decalage
				assert ctr("bonjour") == {"b": 6, "o": 2, "n": 4, "j": 3, "u": 1}
				assert ctr("dab") == {"d": 2, "a": 1}
				assert ctr("dabab") == {"d": 4, "a": 1, "b": 2}
				assert ctr("ACTGACTGACTG") == {"A": 3, "C": 2, "T": 1, "G": 4}
				print ("Tests de création de table de décalage réussis")
		

2. Algorithme de Boyer-Moore. On donne la fonction suivante :


			def boyer_moore(texte, motif):
				table = table_décalage(motif)
				i = 0
				while len(texte) - i >= len(motif):
					j = len(motif)-1
					while texte[i+j] == motif[j]:
						if j == 0:
							return i
						j = j - 1
					if texte[i+len(motif)-1] in table:
						deplacement = table[texte[i+len(motif)-1]]
					else:
						deplacement = len(motif)
					i = i + deplacement
				return -1
		

2.1. Expliquer les lignes 5 à 9

2.2. Expliquer les lignes 10 à 14

2.3. Expliquer la ligne 4

2.4. Que renvoie cette fonction ?