Алгоритм Райта — различия между версиями
Zernov (обсуждение | вклад) (2, 3, 4) |
Zernov (обсуждение | вклад) (→Псевдокод) |
||
Строка 11: | Строка 11: | ||
==Псевдокод== | ==Псевдокод== | ||
+ | Побочные функции | ||
+ | '''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] | |
− | + | <font color=green>//Где ASIZE {{---}} размер алфавита</font> | |
− | + | '''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) | |
− | + | <font color=green>//Проверка на случай поиска вхождения одного символа</font> | |
− | + | '''int''' match = 0 | |
− | + | '''while''' (match < n) | |
− | + | match = findFirst(y, match, n - 1, x[0]) | |
− | + | '''if''' (match != -1) | |
− | + | '''print'''(match) | |
− | + | '''else''' | |
− | + | '''print'''(<font color=green>"No matches"</font>) | |
− | + | '''return''' | |
− | + | bmBc = preBmBc (x, m) | |
− | + | firstCh = x[0]; | |
− | + | middleCh = x[m/2]; | |
− | + | lastCh = x[m - 1]; | |
− | + | <font color=green>//Поиск</font> | |
− | + | '''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'''(<font color=green>"No matches"</font>) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==Асимптотика== | ==Асимптотика== |
Версия 16:43, 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