Бојер-Мур-Хорсполов алгоритам

С Википедије, слободне енциклопедије

У Информатици, Боyер–Мооре–Хорспоол алгоритам ор Хорспоол'с алгоритхм је један алгоритам за налажење подстрингова у стрингс. Ит wас публисхед бy Нигел Хорспоол ин 1980.[1]

То је поједностављена верзија Бојер–Муровог стринг сеарцх алгоритма који је повезан са Кнутх–Моррис–Пратт алгоритмом. Алгортиам мења простор та време у циљу добијања сложеност просечног случаја оф О(Н) на случајном тексту , иако он има О(МН) унајгорем случају, где је дужина патерна M , а дужина стринга који се претражује Н.

Пример примене[уреди | уреди извор]

Ево једног примера имплементације Бојер-Мур-ХорспоЛовог алгоритма, написан у C.

#include <string.h>
#include <limits.h>

/* Returns a pointer to the first occurrence of "needle"
 * within "haystack", or NULL if not found. Works like
 * memmem().
 */

/* Note: In this example needle is a C string. The ending
 * 0x00 will be cut off, so you could call this example with
 * boyermoore_horspool_memmem(haystack, hlen, "abc", sizeof("abc"))
 */
const unsigned char *
boyermoore_horspool_memmem(const unsigned char* haystack, size_t hlen,
                           const unsigned char* needle,   size_t nlen)
{
    size_t scan = 0;
    size_t bad_char_skip[UCHAR_MAX + 1]; /* Officially called:
                                          * bad character shift */

    /* Sanity checks on the parameters */
    if (nlen <= 0 || !haystack || !needle)
        return NULL;

    /* ---- Preprocess ---- */
    /* Initialize the table to default value */
    /* When a character is encountered that does not occur
     * in the needle, we can safely skip ahead for the whole
     * length of the needle.
     */
    for (scan = 0; scan <= UCHAR_MAX; scan = scan + 1)
        bad_char_skip[scan] = nlen;

    /* C arrays have the first byte at [0], therefore:
     * [nlen - 1] is the last byte of the array. */
    size_t last = nlen - 1;

    /* Then populate it with the analysis of the needle */
    for (scan = 0; scan < last; scan = scan + 1)
        bad_char_skip[needle[scan]] = last - scan;

    /* ---- Do the matching ---- */

    /* Search the haystack, while the needle can still be within it. */
    while (hlen >= nlen)
    {
        /* scan from the end of the needle */
        for (scan = last; haystack[scan] == needle[scan]; scan = scan - 1)
            if (scan == 0) /* If the first byte matches, we've found it. */
                return haystack;

        /* otherwise, we need to skip some bytes and start again.
           Note that here we are getting the skip value based on the last byte
           of needle, no matter where we didn't match. So if needle is: "abcd"
           then we are skipping based on 'd' and that value will be 4, and
           for "abcdd" we again skip on 'd' but the value will be only 1.
           The alternative of pretending that the mismatched character was
           the last character is slower in the normal case (E.g. finding
           "abcd" in "...azcd..." gives 4 by using 'd' but only
           4-2==2 using 'z'. */
        hlen     -= bad_char_skip[haystack[last]];
        haystack += bad_char_skip[haystack[last]];
    }

    return NULL;
}

Карактеристике[уреди | уреди извор]

Алгоритам се најбоље показује са дугачким стринговима, када доследно погађа карактер који се не подудара на или близу краја псоледњег бајта тренутне поyиције у пласту сена и псоледњег бајта игле који се више не понављају у целој игли. На пример 32 бајта неедле се заврсава са "з" претражује кроз 255 бајтова сена сламе који нема 'з' бајт , за то ће бити потребно 224 понављања.

Најбољи случај је исти као за Боyер–Мооре стринг сеарцх алгоритам иувелико О нотацији, иако константно изнад иницијализације и за сваку петљу је мање.

Понашање у најгорем слуцају се дешава када је лош карактер који прскачете константно низак (са доње границе од 1 бајта кретања) и када велики део игел одговара пласту сена. Лош карактер прескачете самона парцијалном покдударању, када се коначни карактер игле појављује и у осталим деловима игле, са једним бајтом кретања дешава се када је исти бајту обе последње две позиције.

канонски дегенерисан случај сличан горњем најбољем случају је игла за 'а' бајт праћена са 31 'з' бајтова у пласту сена који се састоји од 255 'з' бајтова. Ово це урадити 31 успешно бајт поређење, 1 бајт поређење које не успе, а затим кренути напред 1 бајт. Овај процес ће се поновити223 пута (255 - 32), сводећи тотално поредјење бајтова на 7,168 (32 * 224).

Најгори случај је знатно већи него за Боyер–Мооре стринг сеарцх алгоритам, иако је јасно да је тешко постићи унормалним случајевима коришћења. такође је вредно напоменути да је овај најгори случај, најгори случај и за наивне (бут усуал) меммем() алгоритме, иако имплементација има тенденцију да буде yнатно оптимизованан (и више је кеш пријатељски).

Види још[уреди | уреди извор]

Референце[уреди | уреди извор]

  1. ^ Р. Н. Хорспоол (1980). „Працтицал фаст сеарцхинг ин стрингс”. Софтwаре - Працтице & Еxпериенце. 10 (6): 501—506. дои:10.1002/спе.4380100608. [Претплата неопходна (помоћ)]. 

Спољашње везе[уреди | уреди извор]