Двусторонний алгоритм

Материал из Викиконспекты
Версия от 20:40, 15 июня 2015; Heatwave (обсуждение | вклад) (Описание алгоритма)
Перейти к: навигация, поиск

Двусторонний алгоритм (англ. Two Way algorithm) — алгоритм поиска подстроки в строке.

Характерные черты

  • требует упорядоченный алфавит
  • этап предобработки занимает O(m) времени и константное количество памяти
  • этап поиска за время O(n)
  • в худшем случае производится 2nm сравнений символов

Описание алгоритма

Строка x разбивается на две части xl и xr так, что x= xl xr. Затем фаза поиска в двустороннем алгоритме состоит в сравнении символов xr слева направо, и затем, если на этом первом этапе не происходит несовпадений, в сравнении символов xl справа налево (второй этап). Фаза предобработки, таким образом, заключается в поиске подходящего разбиения xl xr.

Определение:
Пусть (u,v) — разбиение x. Повторение в (u,v) — слово w такое, что для него выполнены следующие условия:
  1. w — суффикс u или u — суффикс w;
  2. w — префикс v или v — префикс w.

Длина повторения в (u,v) называется локальным периодом; наименьший локальный период записывается как r(u,v).

Каждое разбиение x на (u,v) имеет как минимум одно повторение. Очевидно, что 1r(u,v)|x|

Разбиение x на (u,v) такое, что r(u,v)=per(x) называется критическим разбиением x.


Если (u,v) — критическое разбиение x, то на позиции |u| в x общий и локальный периоды одинаковы. Двусторонний алгоритм находит критическое разбиение (xl,xr) такое, что |xl|<per(x) и длина |xl| минимальна. Чтобы найти критическое разбиение (xl,xr) мы сперва вычислим z — максимальный суффикс x в порядке и максимальный суффикс ˜z для обратного порядка . Затем (xl,xr) выбираются так, что |xl|=max(|z|,|˜z|).

Фаза поиска в двустороннем алгоритме состоит из сравнения символов xr слева направо и символов xl справа налево. Когда происходит несовпадение при просмотре k-го символа в xr, производится сдвиг длиной k. Когда происходит несовпадение при просмотре xl, или когда образец встретился в строке, производится сдвиг длиной per(x). Такие действия приводят к квадратичной работе алгоритма в худшем случае, но этого можно избежать запоминанием префикса: когда производится сдвиг длиной per(x), длина совпадающего префикса образца в начале "окна" (а именно mper(x)) после сдвига запоминается, чтобы не просматривать ее заново при следующем проходе.

Псевдокод

function twoWaySearch(String pattern, String text):
    n = pattern.length
    len1, p1  maxSuffix(pattern, )
    len2, p2  maxSuffix(pattern, )
    if len1  len2
        len = len1
        p = p1
    else
        len = len2
        p = p2
    occurences = 
    pos  0
    memPrefix  0
    if len < n/2 and pattern[1len]  суффикс pattern[len + 1len + p]
        while pos + n  text.length
            i max(l, memPrefix) + 1
            while i  n and pattern[i] = text[pos + i]
                i++
            if i  n
                pos  pos + max(i  len, memPrefix  p + 1)
                memPrefix  0
            else
                j  l
                while j > memPrefix and pattern[j] = text[pos + j]
                    j--
                if j  memPrefix
                    pos  occurences
                pos  pos + p
                memPrefix  n  p
    else
        q max(len, n  len) + 1
        while pos + n  text.length
            i  len + 1
            while i  n and pattern[i] = text[pos + i]
                i++
            if i  n
                pos  pos + i  len
            else
                j  len
                while j > 0 and pattern[j] = text[pos + j]
                    j--
                if j = 0
                    pos  occurences
                pos  pos + q
    return occurences

Источники информации