Двусторонний алгоритм
Двусторонний алгоритм (англ. Two Way algorithm) — алгоритм поиска подстроки в строке.
Характерные черты
- требует упорядоченный алфавит,
- этап предобработки занимает времени и константное количество памяти,
- этап поиска за время .
Описание алгоритма
Строка разбивается на две части и так, что . Затем фаза поиска в двустороннем алгоритме состоит в сравнении символов слева направо, и затем, если на этом первом этапе не происходит несовпадений, в сравнении символов справа налево (второй этап). Фаза предобработки, таким образом, заключается в поиске подходящего разбиения .
| Определение: |
Пусть — разбиение . Повторение в — слово такое, что для него выполнены следующие условия:
Длина повторения в называется локальным периодом; наименьший локальный период записывается как . Каждое разбиение на имеет как минимум одно повторение. Очевидно, что Разбиение на такое, что называется критическим разбиением . |
Если — критическое разбиение , то на позиции в общий и локальный периоды одинаковы. Двусторонний алгоритм находит критическое разбиение такое, что и длина минимальна.
Чтобы найти критическое разбиение мы сперва вычислим — максимальный суффикс в порядке и максимальный суффикс для обратного порядка . Затем выбираются так, что .
Фаза поиска в двустороннем алгоритме состоит из сравнения символов слева направо и символов справа налево. Когда происходит несовпадение при просмотре -го символа в , производится сдвиг длиной . Когда происходит несовпадение при просмотре , или когда образец встретился в строке, производится сдвиг длиной . Такие действия приводят к квадратичной работе алгоритма в худшем случае, но этого можно избежать запоминанием префикса: когда производится сдвиг длиной , длина совпадающего префикса образца в начале "окна" (а именно ) после сдвига запоминается, чтобы не просматривать ее заново при следующем проходе.
Псевдокод
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 (l, memPrefix) + 1
while i n and pattern[i] text[pos + i]
i++
if i n
pos pos + (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 (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