web-dev-qa-db-fra.com

Compréhension et exemple de l'algorithme Boyer Moore?

Je rencontre des problèmes pour comprendre l'algorithme de recherche de chaînes de Boyer Moore.

Je suis le document suivant. Lien

Je ne suis pas en mesure de déterminer ma vraie signification exacte de delta1 et delta2 ici, et comment l'appliquent-ils pour trouver un algorithme de recherche de chaînes. La langue semblait peu vague ..

Si quelqu'un peut m'aider à comprendre cela, ce serait vraiment utile.

Ou, si vous connaissez un autre lien ou document disponible qui est facile à comprendre, veuillez le partager.

Merci d'avance.

31
AGeek

Premier conseil, respirez profondément. Vous êtes clairement stressé, et lorsque vous êtes stressé, la première chose qui arrive, c'est que de gros morceaux de votre cerveau s'arrêtent. Cela rend la compréhension difficile, ce qui augmente le stress et vous avez un problème.

Un délai de 5 minutes pour améliorer votre espace de tête peut sembler impossible à prendre, mais peut être étonnamment utile.

Cela dit, l'algorithme est basé sur un principe simple. Supposons que j'essaie de faire correspondre une sous-chaîne de longueur m. Je vais d'abord regarder le caractère à l'index m. Si ce caractère n'est pas dans ma chaîne, je sais que la sous-chaîne que je veux ne peut pas commencer en caractères aux indices 1, 2, ... , m.

Si ce caractère est dans ma chaîne, je suppose que c'est au dernier endroit de ma chaîne qu'il peut être. Je vais ensuite revenir en arrière et commencer à essayer de faire correspondre ma chaîne à partir de cet endroit de départ possible. Cette information est ma première table.

Une fois que je commence la correspondance depuis le début de la sous-chaîne, lorsque je trouve une incompatibilité, je ne peux pas simplement recommencer à zéro. Je pourrais être partiellement à travers un match commençant à un point différent. Par exemple, si j'essaie de faire correspondre anand dans ananand, anan correspond correctement, a n'est pas un d, mais je viens de faire correspondre an, et je devrais donc recommencer à essayer de faire correspondre mon troisième caractère dans ma sous-chaîne. Cette information "Si j'échoue après avoir trouvé x caractères, je pourrais être sur le yième caractère d'une correspondance" est stockée dans la deuxième table.

Notez que lorsque je ne parviens pas à faire correspondre le deuxième tableau sait à quel point dans un match je pourrais être basé sur ce que je viens de faire correspondre. Le premier tableau sait à quelle distance je pourrais être basé sur le personnage que je viens de voir auquel je n'ai pas réussi à correspondre. Vous voulez utiliser le plus pessimiste de ces deux informations.

Dans cet esprit, l'algorithme fonctionne comme ceci:

start at beginning of string
start at beginning of match
while not at the end of the string:
    if match_position is 0:
        Jump ahead m characters
        Look at character, jump back based on table 1
        If match the first character:
            advance match position
        advance string position
    else if I match:
        if I reached the end of the match:
           FOUND MATCH - return
        else:
           advance string position and match position.
    else:
        pos1 = table1[ character I failed to match ]
        pos2 = table2[ how far into the match I am ]
        if pos1 < pos2:
            jump back pos1 in string
            set match position at beginning
        else:
            set match position to pos2
FAILED TO MATCH
46
btilly

L'idée derrière Boyer-Moore est que si vous commencez à rechercher un motif dans une chaîne commençant par le caractère dernier dans le motif, vous pouvez faire avancer votre recherche de plusieurs caractères lorsque vous frappez une incompatibilité.

Disons que notre modèle p est la séquence de caractères p1, p2, ..., pn et nous recherchons une chaîne s, actuellement avec p alignée afin que pn soit à l'index i dans s.

Par exemple.:

s = WHICH FINALLY HALTS.  AT THAT POINT...
p = AT THAT
i =       ^

Le document B-M fait les observations suivantes:

(1) si nous essayons de faire correspondre un caractère qui n'est pas dans p alors nous pouvons avancer n caractères:

'F' n'est pas dans p, donc nous avançons n caractères:

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =        AT THAT
i =              ^

(2) si nous essayons de faire correspondre un caractère dont la dernière position est k à partir de la fin de p alors nous pouvons avancer k caractères:

La dernière position de 'dans p est 4 à partir de la fin, donc nous avançons 4 caractères:

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =            AT THAT
i =                  ^

Maintenant, nous analysons en arrière à partir de i jusqu'à ce que nous réussissions ou que nous rencontrions un décalage. (3a) si la non-concordance se produit k caractères depuis le début de p et que le caractère non concordant n'est pas dans p, alors nous pouvons avancer (au moins) k personnages.

'L' n'est pas dans p et la non-concordance s'est produite avec p6, nous pouvons donc avancer (au moins) 6 caractères:

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =                  AT THAT
i =                        ^

Cependant, nous pouvons réellement faire mieux que cela. (3b) car nous savons que dans l'ancien i, nous avions déjà fait correspondre certains caractères (1 dans ce cas). Si les caractères correspondants ne correspondent pas au début de p, alors nous pouvons en fait avancer un peu plus (cette distance supplémentaire est appelée "delta2" dans l'article):

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =                   AT THAT
i =                         ^

À ce stade, l'observation (2) s'applique à nouveau, donnant

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =                       AT THAT
i =                             ^

et le bingo! Avaient fini.

113
Rafe