<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<question type="category">
  <category>
    <text>$course$/QCM de NSI/Terminale/Recherche textuelle</text>
  </category>
  <info format="html">
    <text><![CDATA[<p>Recherche d'un motif dans un texte, algorithme naïf (force<br/>
brute), algorithme de Boyer-Moore-Horspool (comparaison de<br/>
droite à gauche, table de décalages), pré-traitement,<br/>
complexités, applications (grep, Ctrl+F, ADN).</p>]]></text>
  </info>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q01 : Position du problème</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>En quoi consiste la <strong>recherche textuelle</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La recherche textuelle est un problème fondamental en<br/>
informatique : elle est utilisée des milliards de fois<br/>
par jour (recherche web, éditeurs de texte, analyse de<br/>
données massives).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Chercher un mot dans un dictionnaire trié</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est un cas particulier qui se résout par<br/>
recherche dichotomique. La recherche textuelle est<br/>
plus générale.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Compter le nombre de caractères dans un texte</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce n'est pas une recherche, juste un<br/>
comptage trivial.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Trier un texte par ordre alphabétique</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec le tri.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Trouver toutes les positions d'un motif (chaîne courte) dans un texte (chaîne longue)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est exactement le problème étudié.<br/>
Applications : Ctrl+F dans un éditeur, <code>grep</code>,<br/>
analyse de séquences ADN, moteurs de recherche.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q02 : Principe de l'algorithme naïf</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel est le principe de l'<strong>algorithme naïf</strong> (force brute) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'algorithme naïf est simple mais inefficace : il<br/>
avance toujours d'une seule position après chaque<br/>
échec, même quand le premier caractère ne correspondait<br/>
pas.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On utilise une table de hachage pour aller plus vite</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est l'idée de l'algorithme de<br/>
Rabin-Karp, pas du naïf.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>On teste chaque position de départ possible et on compare le motif caractère par caractère</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : pour chaque indice <code>i</code> de 0 à<br/>
<code>n - m</code>, on compare le motif au texte à partir de<br/>
la position <code>i</code>. Dès qu'un caractère diffère, on<br/>
passe à la position suivante.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On découpe le texte en deux et on cherche dans chaque moitié</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait du « diviser pour régner », ce<br/>
que ne fait pas l'algorithme naïf.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On compare le motif uniquement à la fin du texte</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on teste <strong>toutes</strong> les positions, pas<br/>
seulement la fin.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q03 : Borne de la boucle</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans l'algorithme naïf, la boucle externe va de 0 à<br/>
quelle valeur (incluse) pour pouvoir aligner un motif<br/>
de longueur <code>m</code> dans un texte de longueur <code>n</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Erreur classique : oublier le <code>+1</code> dans <code>range</code>. Pour<br/>
éviter ce piège, vérifier sur un petit exemple :<br/>
<code>texte = "abc"</code>, <code>motif = "bc"</code>, longueurs <code>n=3</code>,<br/>
<code>m=2</code>. Positions valides : 0, 1. Donc <code>range(2)</code> =<br/>
<code>range(n - m + 1)</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>n - 1</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on dépasserait la fin du texte. À la<br/>
position <code>n - 1</code>, il ne reste qu'un caractère pour<br/>
aligner les <code>m</code> caractères du motif.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>n - m - 1</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on raterait la dernière position valide<br/>
(le motif placé à la toute fin du texte).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>n</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la position <code>n</code> n'existe même pas dans le<br/>
texte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>n - m</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est la dernière position où le<br/>
motif tient encore dans le texte. En Python, on<br/>
écrit donc <code>range(n - m + 1)</code> (la borne supérieure<br/>
de <code>range</code> étant exclusive).</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q04 : Complexité du naïf</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la complexité dans le <strong>pire cas</strong> de<br/>
l'algorithme naïf de recherche textuelle ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le pire cas se rencontre par exemple avec un texte<br/>
<code>"aaaa...a"</code> et un motif <code>"aaab"</code> : à chaque position,<br/>
les m-1 premiers caractères correspondent avant<br/>
l'échec, soit ~ n × m comparaisons.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>O(n + m)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette complexité correspond à<br/>
l'algorithme de Knuth-Morris-Pratt, et non à<br/>
la version naïve.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>O(n × m)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la boucle externe parcourt environ<br/>
n positions ; pour chacune, on peut faire jusqu'à<br/>
m comparaisons. D'où O(n × m), souvent noté<br/>
O(n²) quand n ≫ m.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>O(log n)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune dichotomie dans cet algorithme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>O(n)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : O(n) supposerait une seule comparaison<br/>
par position, ce qui n'est pas le cas dans le<br/>
pire cas.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q05 : Idée clé de Boyer-Moore</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est l'<strong>idée centrale</strong> de l'algorithme de<br/>
Boyer-Moore-Horspool ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Comparer de droite à gauche peut sembler contre-intuitif,<br/>
mais c'est précisément ce qui permet de tirer parti des<br/>
caractères « rares » dans le motif pour faire de grands<br/>
sauts.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Comparer le motif de gauche à droite mais en sautant les voyelles</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec les voyelles. La<br/>
comparaison va de droite à gauche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Utiliser la programmation dynamique avec mémoïsation</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Boyer-Moore n'utilise pas de mémoïsation.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pré-trier le texte pour faire une recherche dichotomique</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on ne peut pas trier un texte sans<br/>
détruire sa structure. La recherche dichotomique<br/>
ne s'applique pas ici.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Comparer le motif de droite à gauche et sauter plusieurs positions en cas d'échec grâce à une table de décalages</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : ces deux idées combinées<br/>
permettent d'éviter de comparer chaque caractère<br/>
du texte. Dans le meilleur cas, on saute m<br/>
positions à chaque fois.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q06 : Applications concrètes</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lequel des outils suivants utilise une variante de la<br/>
recherche textuelle (algorithme naïf ou Boyer-Moore) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La recherche textuelle est l'une des opérations les<br/>
plus exécutées en informatique. Les implémentations<br/>
réelles utilisent souvent Boyer-Moore ou des variantes<br/>
plus avancées (Aho-Corasick pour plusieurs motifs, par<br/>
exemple).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La commande Unix <code>grep</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est exact, mais ce n'est pas la <strong>seule</strong> bonne<br/>
réponse.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Toutes les réponses précédentes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : Ctrl+F, <code>grep</code> et la bio-informatique<br/>
sont trois applications classiques. La recherche<br/>
textuelle est partout.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction Ctrl+F d'un éditeur de texte</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est exact, mais ce n'est pas la <strong>seule</strong> bonne<br/>
réponse. Lis bien toutes les propositions.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'analyse de séquences ADN</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est exact, mais ce n'est pas la <strong>seule</strong> bonne<br/>
réponse.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q07 : Que renvoie l'algorithme ?</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lorsqu'on programme <code>recherche(texte, motif)</code>, quel<br/>
est le retour le plus utile ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Renvoyer la liste des positions est la convention<br/>
standard. La méthode Python <code>str.find()</code> renvoie<br/>
l'indice de la première occurrence (ou -1) ; pour<br/>
toutes les occurrences, il faut écrire sa propre<br/>
fonction ou utiliser <code>re.finditer</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un booléen <code>True</code>/<code>False</code> indiquant la présence</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Insuffisant : on ne sait pas <strong>où</strong> est le motif,<br/>
ni combien de fois il apparaît.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La liste des indices de début de chaque occurrence</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est l'information la plus riche<br/>
(<code>[]</code> si absent, <code>[3, 7]</code> si présent aux<br/>
positions 3 et 7). Un booléen ou un compte<br/>
peuvent en être déduits.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le texte modifié pour retirer le motif</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait un <code>replace</code>, pas une recherche.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La longueur du motif</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est connu d'avance via <code>len(motif)</code>,<br/>
aucun intérêt à la renvoyer.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q08 : Trace de l'algorithme naïf</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Avec l'algorithme naïf, on cherche <code>motif = "ab"</code> dans<br/>
<code>texte = "babab"</code>. Quel est le résultat ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour vérifier rapidement, surligne les caractères du<br/>
texte un par un et identifie les <code>"ab"</code> consécutifs.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[0, 2]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : à la position 0, on a <code>"b"</code> ≠ <code>"a"</code>,<br/>
donc échec immédiat. Le motif ne commence pas en 0.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>[1, 3]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : positions 1 (<code>"ab"</code>) et 3 (<code>"ab"</code>).<br/>
Aux positions 0, 2, 4 le premier caractère est<br/>
<code>"b"</code>, ce qui échoue.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le motif <code>"ab"</code> apparaît bien dans<br/>
<code>"babab"</code> (deux fois).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[1, 2, 3]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : à la position 2, le caractère est <code>"b"</code>,<br/>
donc échec immédiat (<code>"b"</code> ≠ <code>"a"</code>).</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q09 : Pire cas du naïf</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Lequel de ces couples (texte, motif) constitue un<br/>
<strong>pire cas</strong> pour l'algorithme naïf ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le pire cas se rencontre quand le motif et le texte<br/>
partagent un long préfixe commun à chaque position<br/>
(ex. : alphabets très réduits, motifs « presque<br/>
identiques » au texte).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>texte = <code>'hello'</code>, motif = <code>'hello'</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce cas se résout en m comparaisons à la<br/>
position 0. Pas de pire cas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>texte = <code>'aaaaaaaaa'</code>, motif = <code>'aaab'</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : à chaque position, les 3 premiers<br/>
caractères correspondent avant l'échec sur le<br/>
dernier. On effectue ~ 4 × n comparaisons.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>texte = <code>'abracadabra'</code>, motif = <code>'xyz'</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Au contraire : <code>'x'</code> n'apparaît jamais dans le<br/>
texte, donc l'échec est immédiat (1 comparaison<br/>
par position). C'est un <strong>bon</strong> cas pour le naïf.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>texte = <code>'a'</code>, motif = <code>'ab'</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>m &gt; n</code>, la boucle ne s'exécute même pas.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q10 : Direction de comparaison</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans Boyer-Moore-Horspool, par quel caractère du motif<br/>
commence-t-on la comparaison ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Comparer de droite à gauche est la clé : si le<br/>
caractère du texte aligné avec la fin du motif n'est<br/>
pas dans le motif, on peut sauter de m positions sans<br/>
risque.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le premier (gauche)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait l'algorithme naïf. Boyer-Moore<br/>
fait l'inverse.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Le dernier (droite)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on aligne le motif sur le texte<br/>
puis on compare d'abord <code>motif[m-1]</code> avec<br/>
<code>texte[i + m - 1]</code>. C'est ce caractère qui décide<br/>
du décalage à appliquer en cas d'échec.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un caractère choisi au hasard</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la recherche serait non déterministe.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le caractère du milieu</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun algorithme classique ne fait cela.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q11 : Construction de la table</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour le motif <code>"dab"</code> (longueur 3), quelle est la table<br/>
de décalages de Boyer-Moore-Horspool ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Formule : pour le caractère c en position i (la plus<br/>
à droite, hors dernière position), décalage = m - 1 - i.<br/>
Caractères absents du motif : décalage = m.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'d': 3, 'a': 3, 'b': 3}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la valeur 3 (= m) correspond aux<br/>
caractères <strong>absents</strong> du motif.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>{'d': 2, 'a': 1}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : pour <code>'d'</code> en position 0,<br/>
décalage = 3 - 1 - 0 = 2 ; pour <code>'a'</code> en<br/>
position 1, décalage = 3 - 1 - 1 = 1. Le <code>'b'</code><br/>
final est exclu.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'d': 0, 'a': 1, 'b': 2}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est l'inverse, et il ne faut pas<br/>
inclure <code>'b'</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'d': 2, 'a': 1, 'b': 0}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on <strong>n'inclut pas</strong> le dernier caractère<br/>
(<code>'b'</code>) dans la table, sinon on risque un<br/>
décalage de 0 qui ferait boucler l'algorithme.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q12 : Caractère absent du motif</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Avec le motif <code>"dab"</code> (longueur 3), le caractère du<br/>
texte aligné avec la fin du motif est <code>'z'</code>. Quel<br/>
décalage applique-t-on ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est le « cadeau » de Boyer-Moore : un grand alphabet<br/>
(lettres, chiffres, ponctuation) signifie beaucoup de<br/>
caractères absents du motif, donc des sauts maximaux.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le décalage <strong>par défaut</strong> de<br/>
l'algorithme naïf, mais Boyer-Moore fait mieux.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>3 (la longueur du motif)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>'z'</code> n'apparaît pas dans <code>"dab"</code>,<br/>
on peut donc sauter de toute la longueur du<br/>
motif (3) sans risquer de manquer une occurrence.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>0</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un décalage de 0 ferait boucler<br/>
l'algorithme indéfiniment.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>2</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 2 est le décalage pour <code>'d'</code>, pas pour<br/>
un caractère absent.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q13 : Caractère répété</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour le motif <code>"maman"</code> (longueur 5), quelle est la<br/>
table de décalages ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Quand un caractère apparaît plusieurs fois dans le<br/>
motif, on garde la dernière occurrence (avant la fin)<br/>
car elle donne le <strong>plus petit</strong> décalage sûr.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'m': 0, 'a': 3}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>'m'</code> apparaît aussi en position 0, on<br/>
ne garde que la position <strong>la plus à droite</strong><br/>
(hors dernière position).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'m': 4, 'a': 1}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>'m'</code> final est exclu mais celui de<br/>
position 2 donne 5 - 1 - 2 = 2, pas 4.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>{'m': 2, 'a': 1}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>'m'</code> en position 2 (la plus à<br/>
droite hors fin), décalage 5 - 1 - 2 = 2 ;<br/>
<code>'a'</code> en position 3, décalage 5 - 1 - 3 = 1.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'m': 2, 'a': 3, 'n': 0}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on <strong>n'inclut pas</strong> le dernier caractère<br/>
(<code>'n'</code>).</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q14 : Pourquoi exclure le dernier caractère ?</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi exclut-on le dernier caractère du motif lors<br/>
du pré-traitement ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est un point subtil mais essentiel. Sans cette<br/>
exclusion, l'algorithme entrerait dans une boucle<br/>
infinie dès qu'on rencontre un caractère identique au<br/>
dernier du motif.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce qu'il donnerait un décalage de 0, ce qui ferait boucler l'algorithme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : en cas d'égalité avec le dernier<br/>
caractère du motif, on veut chercher la<br/>
précédente occurrence (à gauche), ou décaler de<br/>
m s'il n'y en a pas. Décaler de 0 ferait revenir<br/>
à la même position et boucler.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour économiser de la mémoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le gain mémoire est négligeable. La<br/>
vraie raison est algorithmique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'il est toujours absent du motif</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : il fait évidemment partie du motif<br/>
(puisqu'il en est le dernier caractère).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que Python ne permet pas d'indexer la dernière position</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python le permet sans problème.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q15 : Trace de Boyer-Moore</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On cherche <code>motif = "dab"</code> dans <code>texte = "abracadabra"</code>.<br/>
Au premier alignement (i=0), on compare <code>texte[2]</code><br/>
(<code>'r'</code>) avec <code>motif[2]</code> (<code>'b'</code>). Échec. Sachant que<br/>
<code>'r'</code> n'est pas dans le motif, de combien décale-t-on ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est précisément ce type de saut qui fait la<br/>
puissance de Boyer-Moore : sur du texte naturel<br/>
(alphabet riche), de tels sauts maximaux sont<br/>
fréquents.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>11 (la longueur du texte)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on n'a aucune raison de sauter à la fin<br/>
du texte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>2</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 2 est le décalage de <code>'d'</code>, pas d'un<br/>
caractère absent.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait l'algorithme naïf. Boyer-Moore<br/>
tire parti de l'absence de <code>'r'</code> dans le motif.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>3 (la longueur du motif)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>'r'</code> est absent de <code>"dab"</code>, on<br/>
saute de m = 3 positions. La nouvelle position<br/>
devient i = 3.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q16 : Complexité dans le pire cas</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la complexité de Boyer-Moore-Horspool dans<br/>
le <strong>pire cas</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Point important : l'algorithme de<br/>
Boyer-Moore-Horspool n'apporte aucune garantie<br/>
de complexité dans le pire cas. C'est en moyenne<br/>
et au meilleur cas qu'il se distingue.<br/>
L'algorithme de Knuth-Morris-Pratt, en revanche,<br/>
garantit une complexité en $O(n + m)$, mais avec<br/>
un prétraitement plus coûteux.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>O(n)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : O(n) est atteignable mais pas garanti<br/>
dans le pire cas (la version Horspool n'a pas<br/>
cette garantie).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>O(log n)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucune dichotomie.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>O(n × m)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : dans le pire cas (par exemple,<br/>
motif <code>"aaab"</code> dans <code>"aaaa...a"</code>), la complexité<br/>
rejoint celle du naïf. La force de Boyer-Moore<br/>
est dans le cas moyen et le meilleur cas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>O(n + m)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette complexité correspond à<br/>
l'algorithme de Knuth-Morris-Pratt, et non à<br/>
celui de Boyer-Moore-Horspool.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q17 : Meilleur cas sous-linéaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la complexité dans le <strong>meilleur cas</strong> de<br/>
Boyer-Moore-Horspool ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette propriété sous-linéaire est ce qui rend<br/>
Boyer-Moore particulièrement performant pour les<br/>
motifs longs avec un alphabet varié.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>O(n / m)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : si à chaque échec on saute de m<br/>
positions, on n'effectue qu'environ n/m<br/>
comparaisons. C'est <strong>sous-linéaire</strong> : on trouve<br/>
le motif sans examiner chaque caractère du texte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>O(n)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on fait mieux que linéaire dans le<br/>
meilleur cas. Boyer-Moore peut être sous-linéaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>O(m)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : il faut au minimum traverser le texte<br/>
(modulo les sauts), donc cela dépend de n.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>O(1)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on a toujours besoin de plusieurs<br/>
comparaisons.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q18 : Quand BM n'apporte rien</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans quel cas Boyer-Moore-Horspool n'apporte-t-il<br/>
<strong>aucun gain</strong> par rapport à l'algorithme naïf ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Règle empirique : Boyer-Moore est efficace si motif<br/>
long + alphabet varié. Les pires cas se rencontrent<br/>
avec des séquences quasi-uniformes (séquences ADN<br/>
avec un seul nucléotide, par exemple).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Quand l'alphabet est large</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le cas <strong>favorable</strong> à<br/>
Boyer-Moore (sauts maximaux fréquents).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Quand le texte et le motif ne contiennent presque que des caractères identiques (par exemple uniquement des <code>'a'</code>)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : avec un alphabet réduit, les<br/>
décalages sont presque toujours de 1 et on<br/>
retombe sur un parcours position par position.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Quand le motif est très court</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Partiellement vrai (les sauts sont limités à m),<br/>
mais ce n'est pas le <strong>pire cas</strong>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Quand le texte est très long</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : au contraire, plus le texte est long,<br/>
plus l'écart en valeur absolue grandit.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q19 : Cas particuliers</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que doit renvoyer <code>recherche_naif("abc", "")</code> (motif<br/>
vide) selon la convention de Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cas piège classique. Beaucoup d'implémentations<br/>
doivent traiter ce cas explicitement (par exemple en<br/>
ajoutant <code>if m == 0: return list(range(n + 1))</code>).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Discutable, mais la convention Python (<code>str.find</code>,<br/>
<code>re.finditer</code>) considère le motif vide comme<br/>
présent à toutes les positions.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>[0, 1, 2, 3]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : par convention, le motif vide est<br/>
présent à chaque position du texte, y compris à<br/>
la fin. Pour un texte de longueur 3, cela donne<br/>
n + 1 = 4 positions.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>[0]</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pas seulement à la position 0.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une erreur (<code>ValueError</code>)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python ne lève pas d'erreur pour le<br/>
motif vide.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q20 : Mécanisme de `grep`</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La commande Unix <code>grep</code> (et ses variantes <code>egrep</code>,<br/>
<code>fgrep</code>) utilise principalement quel type d'algorithme<br/>
pour la recherche de motifs simples ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p><code>grep</code> est un excellent exemple d'application directe<br/>
des algorithmes étudiés en NSI. Sa rapidité tient à<br/>
l'utilisation conjointe de Boyer-Moore et d'automates<br/>
compilés.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Algorithme naïf O(n × m)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>grep</code> est très optimisé. Le naïf est<br/>
trop lent pour des fichiers volumineux.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Programmation dynamique</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la programmation dynamique sert pour<br/>
d'autres problèmes (alignement de séquences,<br/>
distance d'édition).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Recherche dichotomique sur le texte</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : impossible sans pré-trier le texte.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Variantes de Boyer-Moore (avec <code>fgrep</code> ou les motifs sans expression régulière)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>fgrep</code> (ou <code>grep -F</code>) utilise<br/>
des variantes de Boyer-Moore pour les motifs<br/>
fixes. Pour les expressions régulières, <code>grep</code><br/>
utilise des automates finis (DFA/NFA).</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q21 : Nombre d'alignements de BM</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On cherche <code>motif = "dab"</code> (longueur 3) dans<br/>
<code>texte = "abracadabra"</code> (longueur 11) avec<br/>
Boyer-Moore-Horspool. Combien d'alignements distincts<br/>
du motif sont effectués (i.e. valeurs successives de<br/>
<code>i</code>) avant la fin de l'algorithme ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Trace complète : i=0, échec sur 'r' (saute 3) ; i=3,<br/>
échec sur 'a' (saute 1) ; i=4, échec sur 'd' (saute<br/>
2) ; i=6, succès. Quatre alignements pour 9 dans le<br/>
naïf : économie de plus de la moitié.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>11</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on ne teste pas chaque position du<br/>
texte (c'est tout l'intérêt de Boyer-Moore).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>2</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : trop peu, on doit bien tester plusieurs<br/>
positions intermédiaires.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>9 (comme l'algorithme naïf)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Boyer-Moore fait moins d'alignements<br/>
grâce aux sauts.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>4</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : i = 0 → saute de 3 → i = 3 →<br/>
saute de 1 → i = 4 → saute de 2 → i = 6 (motif<br/>
trouvé) → i = 7 → fin. Soit 4 alignements<br/>
distincts (0, 3, 4, 6) avant détection.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q22 : Table d'un motif complexe</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la table de décalages de<br/>
Boyer-Moore-Horspool pour le motif <code>"abracadabra"</code><br/>
(longueur 11) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Méthode systématique : balayer le motif de droite à<br/>
gauche en s'arrêtant <strong>avant</strong> le dernier caractère.<br/>
Pour chaque nouveau caractère rencontré, calculer<br/>
m - 1 - i.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'a': 1, 'b': 2, 'r': 3, 'c': 4, 'd': 5}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : valeurs incorrectes. Il faut prendre la<br/>
dernière position (hors fin) de chaque<br/>
caractère.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>{'a': 3, 'b': 2, 'r': 1, 'c': 6, 'd': 4}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse. Dernière position (hors fin) de<br/>
chaque caractère : a en 7 → 11-1-7=3 ; b en 8 →<br/>
11-1-8=2 ; r en 9 → 11-1-9=1 ; c en 4 → 11-1-4=6 ;<br/>
d en 6 → 11-1-6=4. Le <code>'a'</code> final est exclu.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'a': 0, 'b': 1, 'r': 2, 'c': 3, 'd': 4}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce sont les positions, pas les<br/>
décalages. Le décalage est m - 1 - position.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>{'a': 3, 'b': 2, 'r': 1, 'c': 6, 'd': 4, 'a': 0}</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le <code>'a'</code> final est <strong>exclu</strong> ; on n'a<br/>
qu'une seule entrée pour <code>'a'</code> (la position 7).</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q23 : Choix d'algorithme</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On veut chercher un motif de longueur 100 dans un<br/>
texte ADN (alphabet <code>{A, C, G, T}</code>) de 10⁹<br/>
nucléotides. Quel algorithme est le <strong>plus pertinent</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le programme de NSI s'arrête à Boyer-Moore-Horspool,<br/>
mais en bio-informatique réelle, on utilise des<br/>
structures de données plus avancées (arbres de<br/>
suffixes, FM-index) pour gérer des génomes entiers.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un algorithme spécialisé (Knuth-Morris-Pratt, Aho-Corasick, ou une indexation par transformée de Burrows-Wheeler) garantissant une complexité en $O(n + m)$</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Pour des séquences ADN volumineuses, on<br/>
utilise l'algorithme de Knuth-Morris-Pratt,<br/>
celui d'Aho-Corasick (pour plusieurs motifs<br/>
recherchés simultanément), ou des<br/>
indexations précalculées (les outils BWA et<br/>
Bowtie reposent sur la transformée de<br/>
Burrows-Wheeler).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Algorithme naïf, suffisant pour la plupart des cas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : avec n = 10⁹ et m = 100, le pire cas<br/>
serait 10¹¹ comparaisons. Trop lent.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Recherche dichotomique</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : impossible sans tri du texte (ce qui<br/>
détruirait la séquence).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Boyer-Moore-Horspool, simple à implémenter mais limité par l'alphabet réduit</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est mieux que le naïf mais l'alphabet à 4<br/>
symboles limite les sauts. Il existe mieux.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q24 : Bug subtil</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un élève écrit la boucle externe de Boyer-Moore comme<br/>
<code>while i &lt; n - m:</code> au lieu de <code>while i &lt;= n - m:</code>.<br/>
Quel est l'effet ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Bug très classique des problèmes de bornes :<br/>
<code>&lt;</code> versus <code>&lt;=</code>. Un test sur <code>texte = "abc"</code>,<br/>
<code>motif = "bc"</code> détecte immédiatement le bug : <code>n - m</code><br/>
vaut 1, donc <code>while i &lt; 1</code> ne teste que i=0 et rate<br/>
le motif en position 1.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'algorithme entre dans une boucle infinie</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la boucle se termine bien, juste trop<br/>
tôt.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'algorithme est plus rapide (gain négligeable)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la performance n'est pas le problème.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'algorithme renvoie des positions incorrectes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les positions trouvées sont correctes,<br/>
on en rate juste certaines (celles à la fin).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>L'algorithme rate les motifs situés à la toute fin du texte</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la position <code>i = n - m</code> est la<br/>
dernière où le motif tient encore dans le texte.<br/>
La condition <code>i &lt; n - m</code> exclut cette position<br/>
et rate les occurrences finales.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q25 : Comparaison synthétique</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Parmi les affirmations suivantes sur les algorithmes<br/>
de recherche textuelle vus en NSI, laquelle est<br/>
<strong>fausse</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>« Toujours plus rapide » est presque toujours faux en<br/>
algorithmique : chaque algorithme a ses cas<br/>
favorables et ses pathologies. Le choix dépend du<br/>
profil des données.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'algorithme naïf a une complexité O(n × m) dans le pire cas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : c'est sa complexité de pire cas standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Boyer-Moore-Horspool peut atteindre O(n / m) dans le meilleur cas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : c'est sa propriété sous-linéaire<br/>
remarquable.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour de nombreux motifs simultanés, on préfère Aho-Corasick à Boyer-Moore</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : Aho-Corasick traite plusieurs motifs en<br/>
un seul passage du texte (utilisé par les<br/>
antivirus, par exemple).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Boyer-Moore-Horspool est toujours plus rapide que l'algorithme naïf</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Faux (donc bonne réponse) : sur certains<br/>
textes-pathologiques (alphabet réduit, motif<br/>
répétitif), Boyer-Moore retombe au pire cas du<br/>
naïf, voire est <strong>plus lent</strong> à cause de la<br/>
gestion des décalages.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q26 : Code de l'algorithme naïf</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle fonction Python implémente correctement<br/>
l'algorithme naïf de recherche textuelle, en<br/>
renvoyant la liste des indices de début de chaque<br/>
occurrence ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cet algorithme illustre clairement le schéma de<br/>
double boucle (externe sur les positions, interne<br/>
sur la comparaison caractère par caractère).<br/>
C'est la base pédagogique avant d'aborder<br/>
Boyer-Moore.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def recherche_naif(texte, motif):
    for i in range(len(texte)):
        if texte[i] == motif:
            return i
    return -1</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on compare un seul caractère du texte<br/>
avec <strong>toute la chaîne</strong> motif, ce qui est<br/>
toujours faux (sauf si le motif est de<br/>
longueur 1). Et on ne renvoie qu'une seule<br/>
position au lieu de toutes les occurrences.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>def recherche_naif(texte, motif):
    positions = []
    n, m = len(texte), len(motif)
    for i in range(n - m + 1):
        j = 0
        while j &lt; m and texte[i + j] == motif[j]:
            j += 1
        if j == m:
            positions.append(i)
    return positions</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la boucle externe parcourt les<br/>
positions valides ; la boucle interne compare<br/>
caractère par caractère et s'arrête au premier<br/>
échec. Si on a comparé tous les caractères du<br/>
motif (<code>j == m</code>), on a trouvé une occurrence.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def recherche_naif(texte, motif):
    return [i for i, c in enumerate(texte) if c == motif[0]]</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on ne vérifie que le premier<br/>
caractère, pas le motif complet. Pour<br/>
<code>motif = "abc"</code> dans <code>"abracadabra"</code>, on<br/>
renverrait toutes les positions de <code>'a'</code>,<br/>
y compris celles où <code>"abc"</code> n'est pas le<br/>
début.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>def recherche_naif(texte, motif):
    positions = []
    for i in range(len(texte)):
        if texte[i:i + len(motif)] == motif:
            positions.append(i)
    return positions</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette version fonctionne, mais utilise une<br/>
comparaison de tranches qui repose sur<br/>
l'opération <code>==</code> de Python. Elle masque la<br/>
mécanique caractère par caractère qu'on<br/>
souhaite illustrer dans l'algorithme naïf<br/>
pédagogique. De plus, la boucle va trop loin<br/>
(jusqu'à <code>len(texte) - 1</code>), ce qui peut<br/>
provoquer des comparaisons inutiles avec des<br/>
tranches plus courtes que <code>m</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Recherche textuelle — Q27 : Saut maximal en pratique</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Avec le motif <code>motif = "exercice"</code> (longueur 8) et<br/>
le texte <code>"l'élève fait son devoir"</code>, on aligne le<br/>
motif au tout début. Le caractère du texte aligné<br/>
avec la fin du motif est <code>'a'</code> (de « fait »).<br/>
Sachant que <code>'a'</code> n'apparaît pas dans <code>"exercice"</code>,<br/>
de combien décale-t-on ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>C'est ce mécanisme de saut maximal qui rend<br/>
Boyer-Moore sous-linéaire dans le meilleur cas :<br/>
pour des textes en alphabet riche (lettres latines,<br/>
ponctuation), la plupart des caractères du texte<br/>
sont absents du motif, et on saute donc presque<br/>
toujours de <code>m</code> positions.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>1 position</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est ce que ferait l'algorithme naïf<br/>
(avancer d'une position après chaque échec).<br/>
L'intérêt de Boyer-Moore est précisément de<br/>
sauter davantage en s'appuyant sur la table<br/>
de décalages.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>0 position (on doit tester à nouveau au même endroit)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un décalage de 0 ferait boucler<br/>
l'algorithme indéfiniment. C'est précisément<br/>
pour cela qu'on exclut le dernier caractère<br/>
du motif lors du pré-traitement de la table<br/>
de décalages.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>4 positions (la moitié de la longueur du motif)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Boyer-Moore ne fait pas de demi-saut<br/>
arbitraire. La règle est claire : si le<br/>
caractère est absent du motif, on saute de<br/>
la longueur entière <code>m</code> du motif.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>8 positions (la longueur du motif)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>'a'</code> n'étant pas présent dans<br/>
<code>"exercice"</code>, on peut sauter de toute la<br/>
longueur du motif sans risque de manquer une<br/>
occurrence. C'est le saut maximal possible.<br/>
Sur du texte courant, ce type de saut est<br/>
fréquent et explique la rapidité de<br/>
Boyer-Moore.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
