Двусторонний алгоритм — различия между версиями
Heatwave (обсуждение | вклад) (Менее адский псевдокод, комментарии) |
Heatwave (обсуждение | вклад) |
||
| Строка 50: | Строка 50: | ||
memPrefix <tex>\leftarrow</tex> 0 | memPrefix <tex>\leftarrow</tex> 0 | ||
'''while''' pos + pattern.length <tex>\leqslant</tex> text.length | '''while''' pos + pattern.length <tex>\leqslant</tex> text.length | ||
| − | <font color=green>// | + | <font color=green>//первый этап: просмотр <tex>v</tex> слева направо</font> |
i <tex>\leftarrow \max</tex>(l, memPrefix) + 1 | i <tex>\leftarrow \max</tex>(l, memPrefix) + 1 | ||
'''while''' i <tex>\leqslant</tex> pattern.length '''and''' pattern[i] <tex>=</tex> text[pos + i] | '''while''' i <tex>\leqslant</tex> pattern.length '''and''' pattern[i] <tex>=</tex> text[pos + i] | ||
| Строка 58: | Строка 58: | ||
memPrefix <tex>\leftarrow</tex> 0 | memPrefix <tex>\leftarrow</tex> 0 | ||
'''else''' | '''else''' | ||
| − | <font color=green>// | + | <font color=green>//второй этап: просмотр <tex>u</tex> справа налево</font> |
j <tex>\leftarrow</tex> l | j <tex>\leftarrow</tex> l | ||
'''while''' j <tex> > </tex> memPrefix '''and''' pattern[j] <tex>=</tex> text[pos + j] | '''while''' j <tex> > </tex> memPrefix '''and''' pattern[j] <tex>=</tex> text[pos + j] | ||
| Строка 67: | Строка 67: | ||
memPrefix <tex>\leftarrow</tex> pattern.length <tex>-</tex> p | memPrefix <tex>\leftarrow</tex> pattern.length <tex>-</tex> p | ||
'''return''' occurences | '''return''' occurences | ||
| + | |||
| + | == Ценность алгоритма == | ||
| + | Двусторонний алгоритм отчасти похож на алгоритм Бойера-Мура (просмотр символов справа налево и сдвиг позиции при несовпадении на втором этапе), и в лучшем случае работает немногим медленнее его, а в худшем {{---}} значительно превосходит<ref>[http://monge.univ-mlv.fr/~mac/Articles-PDF/CP-1991-jacm.pdf Journal of the Association for Computing Machinery, Vol. 38, No, 1, July 1991] Оценки скорости работы</ref>, но главное отличие двустороннего алгоритма от алгоритмов Кнута-Морриса-Пратта и Бойера-Мура {{---}} константное количество затрачиваемой дополнительной памяти. | ||
== Источники информации == | == Источники информации == | ||
* [http://monge.univ-mlv.fr/~mac/Articles-PDF/CP-1991-jacm.pdf Оригинал статьи (M. Crochemore, D. Perrin)] | * [http://monge.univ-mlv.fr/~mac/Articles-PDF/CP-1991-jacm.pdf Оригинал статьи (M. Crochemore, D. Perrin)] | ||
* [http://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260 Краткое описание алгоритма, пример работы] | * [http://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260 Краткое описание алгоритма, пример работы] | ||
| + | |||
| + | == Примечания == | ||
| + | <references/> | ||
== См. также == | == См. также == | ||
Версия 01:37, 16 июня 2015
Двусторонний алгоритм (англ. Two Way algorithm) — алгоритм поиска подстроки в строке.
Содержание
Характерные черты
- требует упорядоченный алфавит,
- этап предобработки занимает времени и константное количество памяти,
- этап поиска за время , где m — длина образца, а n — длина текста.
Описание алгоритма
Строка разбивается на две части и так, что . Затем фаза поиска в двустороннем алгоритме состоит в сравнении символов слева направо, и затем, если на первом этапе не происходит несовпадений, в сравнении символов справа налево (второй этап). Фаза предобработки, таким образом, заключается в поиске подходящего разбиения .
| Определение: |
| — разбиение строки , если . |
| Определение: |
Пусть — разбиение . Повторение в — слово такое, что для него выполнены следующие условия:
|
| Определение: |
| Длина повторения в называется локальным периодом; наименьший локальный период записывается как . Каждое разбиение на имеет как минимум одно повторение. Очевидно, что |
| Определение: |
| Разбиение на такое, что называется критическим разбиением . |
Если — критическое разбиение , то на позиции в общий и локальный периоды одинаковы. Двусторонний алгоритм находит критическое разбиение такое, что и длина минимальна.
Чтобы найти критическое разбиение мы сперва вычислим — максимальный суффикс в лексикографическом порядке, характерном для заданного алфавита и максимальный суффикс для обратного лексикографического порядка . Затем выбираются так, что .
Фаза поиска в двустороннем алгоритме состоит из сравнения символов слева направо и символов справа налево. Когда происходит несовпадение при просмотре -го символа в , производится сдвиг длиной . Когда происходит несовпадение при просмотре или когда образец встретился в строке, производится сдвиг длиной . Такие действия приводят к квадратичной работе алгоритма в худшем случае, но этого можно избежать запоминанием префикса: когда производится сдвиг длиной , длина совпадающего префикса образца в начале "окна" (а именно ) после сдвига запоминается, чтобы не просматривать ее заново при следующем проходе.
Псевдокод
function twoWaySearch(String pattern, String text):
//предобработка вычисление критической позиции (в которой строка делится на и )
l1, p1 maxSuffix(pattern, )
l2, p2 maxSuffix(pattern, )
if l1 l2
l = l1
p = p1
else
len = l2
p = p2
// период , такая критическая позиция, что
occurences =
pos 0
memPrefix 0
while pos + pattern.length text.length
//первый этап: просмотр слева направо
i (l, memPrefix) + 1
while i pattern.length and pattern[i] text[pos + i]
i++
if i pattern.length
pos pos + (i l, 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 pattern.length p
return occurences
Ценность алгоритма
Двусторонний алгоритм отчасти похож на алгоритм Бойера-Мура (просмотр символов справа налево и сдвиг позиции при несовпадении на втором этапе), и в лучшем случае работает немногим медленнее его, а в худшем — значительно превосходит[1], но главное отличие двустороннего алгоритма от алгоритмов Кнута-Морриса-Пратта и Бойера-Мура — константное количество затрачиваемой дополнительной памяти.
Источники информации
Примечания
- ↑ Journal of the Association for Computing Machinery, Vol. 38, No, 1, July 1991 Оценки скорости работы