Алгоритм Райта — различия между версиями
Zernov (обсуждение | вклад) (→Псевдокод) |
Zernov (обсуждение | вклад) (→Асимптотика) |
||
| Строка 65: | Строка 65: | ||
==Асимптотика== | ==Асимптотика== | ||
| − | * Фаза препроцессинга требует <tex>O(m)</tex> времени и памяти | + | * Фаза препроцессинга требует <tex>O(m + \sigma)</tex> времени и памяти, где <tex>\sigma</tex> {{---}} размер алфавита. |
* В худшем случае поиск требует <tex>O(m \cdot n)</tex> сравнений. | * В худшем случае поиск требует <tex>O(m \cdot n)</tex> сравнений. | ||
| + | '''Пример:''' текст, состоящий только из букв <tex>a</tex> и образец <tex>aa..baa</tex>. В таком случае, <tex>BmBc[a]</tex> будет равен <tex>1</tex>, то есть после каждой фазы сравнений мы будем сдвигаться на <tex>1</tex>. Значит, всего будет <tex>n</tex> фаз сравнений, а каждая фаза будет работать за <tex>m - 2</tex>, поскольку расхождение будет только в <tex>3</tex> с конца символе, то мы сравним сначала последний, потом первый, потом средний, а затем пойдем с самого начала, сравнивая все символы подряд. Итого получаем асимптотику <tex>O(m \cdot n)</tex> | ||
| + | * В лучшем случае требует <tex > \Omega(n / m)</tex> сравнений. | ||
| + | '''Пример:''' текст, вида <tex>a..ba..ab..a</tex> и образец <tex>ba..ab</tex>. В таком случае, <tex>BmBc[b]</tex> будет равен <tex>m - 1</tex>. Значит, всего будет не более чем <tex>n / (m - 1)</tex> фаз сравнений, а каждая фаза (кроме той, в которой мы нашли вхождение строки) будет работать за <tex>1</tex>, поскольку расхождение будет уже в последних символах. Итого получаем асимптотику <tex > \Omega(n / m)</tex> | ||
==Пример== | ==Пример== | ||
Версия 16:57, 27 марта 2016
Алгоритм Райта (англ. Raita algorithm) — алгоритм поиска подстроки в строке, который опубликовал Тим Райта в 1991 году, являющийся модификацией алгоритма Бойера-Мура и улучшающий его асимптотику
Описание алгоритма
Алгоритм Райта ищет образец в заданном тексте сравнивания их символы. Сравнение происходит в следующем порядке (окном текста будем называть последовательность символов , где — длина образца ):
- Последний символ образца сравнивается с самым правым символом окна.
- Если они совпадают, то первый символ сравнивается с самым левым символом окна.
- Если они опять совпали, то сравниваются символы, находящиеся посередине образца и окна.
Если все шаги прошли успешно, то начинаем сравнивать образец и текст посимвольно в обычном порядке, начиная с второго с конца символа. В противном случае, выполняем функцию сдвига плохого символа, которая обрабона в стадии препроцессинга. Эта функция аналогична той, которая была использована в фазе препроцессинга алгоритма Бойера-Мура. Кроме того, в третьем шаге можно брать не средний символ, а случайный, либо с каким-то определенным индексом, в зависимости от специфики текста.
Псевдокод
Побочные функции
int findFirst(char[] y, int fromIndex, int toIndex, char symbol)
for (i = fromIndex .. toIndex)
if (y[i] == symbol)
return i
return -1
boolean restEquals(char[] y, int fromIndex, char[] x, int toIndex)
for (i = fromIndex .. toIndex)
if (y[i] != x[i - fromIndex + 1])
return false
return true
Стадия препроцессинга (совпадает со стадией препроцессинга в алгоритме Бойера-Мура)
int[] preBmBc(char[] x, int m)
int[] result = int[ASIZE]
//Где ASIZE — размер алфавита
for (i = 0 .. ASIZE - 1)
result[i] = m;
for (i = 0 .. m - 2)
result[x[i]] = m - i - 1;
return result
Основная стадия алгоритма
void RAITA(char[] x, int m, char[] y, int n)
int[] bmBc
char c, firstCh, middleCh, lastCh;
if (m == 0)
return
else if (m == 1)
//Проверка на случай поиска вхождения одного символа
int match = 0
while (match < n)
match = findFirst(y, match, n - 1, x[0])
if (match != -1)
print(match)
else
print("No matches")
return
bmBc = preBmBc (x, m)
firstCh = x[0];
middleCh = x[m/2];
lastCh = x[m - 1];
//Поиск
int j = 0
while (j <= n - m)
c = y[j + m - 1]
if (lastCh == c && middleCh == y[j + m / 2] && firstCh == y[j] &&
restEquals(y, j + 1, x, j + m - 2))
print(j)
return
j += bmBc[c];
print("No matches")
Асимптотика
- Фаза препроцессинга требует времени и памяти, где — размер алфавита.
- В худшем случае поиск требует сравнений.
Пример: текст, состоящий только из букв и образец . В таком случае, будет равен , то есть после каждой фазы сравнений мы будем сдвигаться на . Значит, всего будет фаз сравнений, а каждая фаза будет работать за , поскольку расхождение будет только в с конца символе, то мы сравним сначала последний, потом первый, потом средний, а затем пойдем с самого начала, сравнивая все символы подряд. Итого получаем асимптотику
- В лучшем случае требует сравнений.
Пример: текст, вида и образец . В таком случае, будет равен . Значит, всего будет не более чем фаз сравнений, а каждая фаза (кроме той, в которой мы нашли вхождение строки) будет работать за , поскольку расхождение будет уже в последних символах. Итого получаем асимптотику
Пример
Пусть нам дана строка и образец
В итоге, чтобы найти одно вхождение образца длиной в образце длиной нам понадобилось сравнений символов
Источники информации
- RAITA T., 1992, Tuning the Boyer-Moore-Horspool string searching algorithm, Software - Practice & Experience, 22(10):879-884.
- www-igm.univ-mlv.fr — Raita algorithm
- en.wikipedia.org — Raita algorithm
