Алгоритм Апостолико-Крочемора — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
Строка 20: Строка 20:
  
 
Введем обозначение: пусть <tex>t[i]</tex> {{---}} длина наибольшего бордера для <tex>x[0 .. i - 1]</tex> за которым следует символ <tex>c \neq x[i]</tex> и <tex>-1</tex> если нет такого помеченного бордера, где <tex>0 < i \le m</tex> (<tex>t[0] = -1</tex>). Затем после сдвига сравнение можно продолжить между символами <tex>x[t[i]]</tex> и <tex>y[i + j]</tex> не потеряв  никакого вхождения <tex>x</tex> в <tex>y</tex> и избежав отступа по тексту (смотри рис. 1).
 
Введем обозначение: пусть <tex>t[i]</tex> {{---}} длина наибольшего бордера для <tex>x[0 .. i - 1]</tex> за которым следует символ <tex>c \neq x[i]</tex> и <tex>-1</tex> если нет такого помеченного бордера, где <tex>0 < i \le m</tex> (<tex>t[0] = -1</tex>). Затем после сдвига сравнение можно продолжить между символами <tex>x[t[i]]</tex> и <tex>y[i + j]</tex> не потеряв  никакого вхождения <tex>x</tex> в <tex>y</tex> и избежав отступа по тексту (смотри рис. 1).
 +
 +
===Псевдокод===
 +
    empty
 +
 +
Пусть теперь <tex>l {{=}} 0</tex>, если <tex>x = c ^ m</tex> и <tex>c \in \Sigma</tex>, иначе <tex>l</tex> равно позиции первого элемента, который не равен <tex>x[0]</tex> (<tex>x {{=}} (a ^ l)bu</tex>, где <tex>a</tex> и <tex>b \in \Sigma</tex>, а <tex>u \in \Sigma^*</tex> и <tex>a \neq b</tex>). На каждой итерации алгоритма мы выполняем сравнения с шаблоном в следующем порядке: <tex>l, l + 1, \ldots , m - 2, m - 1, 0, 1, \ldots , l - 1</tex>.
 +
 +
Во время поиска вхождений мы рассматриваем данную тройку <tex>(i, j, k)</tex> где:
 +
* шаблон сравнивается с <tex>y[j, \ldots , j + m - 1]</tex>
 +
* <tex>0 \le k \le l</tex> и <tex>x[0, \ldots, k - 1] {{=}} y[j, \ldots , j + k - 1]</tex>
 +
* <tex>l \le i < m</tex> и <tex>x[l, \ldots, i - 1] {{=}} y[j + l, \ldots , i + j - 1]</tex>
 +
Вначале инициализируем эту тройку <tex>(l, 0, 0)</tex>.
 +
Теперь опишем, как по уже вычисленной тройке <tex>(i, j, k)</tex> перейти к следующей.
 +
Возможны три случая в зависимости от значения <tex>i</tex>:

Версия 20:34, 4 марта 2016

Эта статья находится в разработке!

Алгоритм Апостолико-Крочемора (англ. Apostolico-Crochemore algorithm) - вариация Алгоритма Бойера-Мура.

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

  • этап предобработки занимает [math]O(m)[/math] времени и константное количество памяти,
  • этап поиска занимает [math]O(n)[/math] времени,
  • выполняет [math]\frac{3}{2} n[/math] сравнений в худшем случае.

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

Нам даны: [math]y[/math] — текст, [math]x[/math] — образец, [math]m {{=}} |x|[/math], [math]n {{=}} |y|[/math].

Для начала рассмотрим ситуацию, когда мы сравниваем наш образец с [math]y[j \ldots j + m - 1][/math]. Предположим, что первое несовпадение произойдет между [math]x[i][/math] и [math]y[i + j][/math] при [math]0 \lt i \lt m[/math]. Тогда [math]x[0 \ldots i - 1] {{=}} y[j \ldots i + j - 1] {{=}} u[/math] и [math]a {{=}} x[i] \neq y[i + j] {{=}} b[/math]. Когда сдвиг возможен, разумно ожидать что префикс [math]v[/math] шаблона совпадет c некоторым суффиксом [math]u[/math]. Более того, если мы ходим избежать несовпадения при сдвиге, то нужно чтобы символ, следующий за префиксом [math]v[/math] в шаблоне, не совпадал с [math]a[/math]. Такой наибольший префикс [math]v[/math] называется помеченным бордером строки [math]u[/math].


Определение:
помеченный бордер (англ. tagged border) строки [math]\beta[/math] — строка [math]\alpha : \forall i = 1 \ldots n - 1, \alpha[i] {{=}} \beta[i + (m - n)], \alpha[n] \neq \beta[m], n {{=}} |\alpha|, m {{=}} |\beta|[/math].


Введем обозначение: пусть [math]t[i][/math] — длина наибольшего бордера для [math]x[0 .. i - 1][/math] за которым следует символ [math]c \neq x[i][/math] и [math]-1[/math] если нет такого помеченного бордера, где [math]0 \lt i \le m[/math] ([math]t[0] = -1[/math]). Затем после сдвига сравнение можно продолжить между символами [math]x[t[i]][/math] и [math]y[i + j][/math] не потеряв никакого вхождения [math]x[/math] в [math]y[/math] и избежав отступа по тексту (смотри рис. 1).

Псевдокод

   empty

Пусть теперь [math]l {{=}} 0[/math], если [math]x = c ^ m[/math] и [math]c \in \Sigma[/math], иначе [math]l[/math] равно позиции первого элемента, который не равен [math]x[0][/math] ([math]x {{=}} (a ^ l)bu[/math], где [math]a[/math] и [math]b \in \Sigma[/math], а [math]u \in \Sigma^*[/math] и [math]a \neq b[/math]). На каждой итерации алгоритма мы выполняем сравнения с шаблоном в следующем порядке: [math]l, l + 1, \ldots , m - 2, m - 1, 0, 1, \ldots , l - 1[/math].

Во время поиска вхождений мы рассматриваем данную тройку [math](i, j, k)[/math] где:

  • шаблон сравнивается с [math]y[j, \ldots , j + m - 1][/math]
  • [math]0 \le k \le l[/math] и [math]x[0, \ldots, k - 1] {{=}} y[j, \ldots , j + k - 1][/math]
  • [math]l \le i \lt m[/math] и [math]x[l, \ldots, i - 1] {{=}} y[j + l, \ldots , i + j - 1][/math]

Вначале инициализируем эту тройку [math](l, 0, 0)[/math]. Теперь опишем, как по уже вычисленной тройке [math](i, j, k)[/math] перейти к следующей. Возможны три случая в зависимости от значения [math]i[/math]: