Алгоритм Колусси — различия между версиями
Kabanov (обсуждение | вклад) м |
Kabanov (обсуждение | вклад) |
||
Строка 2: | Строка 2: | ||
Отметим, что нумерация символов строк и элементов массива у нас начинается с <tex>0</tex>. | Отметим, что нумерация символов строк и элементов массива у нас начинается с <tex>0</tex>. | ||
− | + | Обозначим <tex>Kmp</tex> [[Префикс-функция|префикс-функцию]]. При этом она должна быть определена для <tex>x[0] \dots x[m-1]</tex> и иметь значение <tex>-1</tex> по умолчанию. | |
{{Определение | {{Определение | ||
− | |definition= | + | |definition= |
− | + | Для всех <tex>i</tex> таких, что <tex>0 \leqslant i \leqslant m-1</tex> выполняется:<br/> | |
− | + | <tex>\mathrm{Kmin}(i) = \begin{cases} | |
− | + | d, & \mbox{if } d > 0\ and\ x[0 \dots i-1-d]=x[d \dots i-1]\ and\ x[i-d] \neq x[i]\\ | |
− | + | 0, & \mbox{otherwise} | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
\end{cases}</tex> | \end{cases}</tex> | ||
}} | }} | ||
− | |||
− | |||
− | |||
− | |||
==Псевдокод== | ==Псевдокод== | ||
− | |||
'''Наивный вариант''' | '''Наивный вариант''' | ||
'''int'''[] buildHmax('''char'''[] x, '''int''' m): | '''int'''[] buildHmax('''char'''[] x, '''int''' m): | ||
Строка 57: | Строка 46: | ||
На каждой итерации цикла увеличивается либо переменная <tex>i</tex>, либо <tex>k</tex> (или переменная <tex>q</tex>, которая используется в конечном счете для обновления <tex>k</tex>). Поскольку <tex>i = 1</tex> и <tex>k = 1</tex> в начале и <tex>i < k = m + 1</tex> в конце алгоритма, количество итераций алгоритма не превосходит <tex>2 \cdot m</tex>. Следовательно функция требует <tex>O(m)</tex> времени и памяти. | На каждой итерации цикла увеличивается либо переменная <tex>i</tex>, либо <tex>k</tex> (или переменная <tex>q</tex>, которая используется в конечном счете для обновления <tex>k</tex>). Поскольку <tex>i = 1</tex> и <tex>k = 1</tex> в начале и <tex>i < k = m + 1</tex> в конце алгоритма, количество итераций алгоритма не превосходит <tex>2 \cdot m</tex>. Следовательно функция требует <tex>O(m)</tex> времени и памяти. | ||
− | Функция для построения массива <tex>Kmin</tex>. | + | Функция для построения массива <tex>\mathrm{Kmin}</tex>. |
'''int'''[] buildKmin('''int'''[] hmax, '''int''' m) | '''int'''[] buildKmin('''int'''[] hmax, '''int''' m) | ||
'''int''' kmin[m] | '''int''' kmin[m] | ||
Строка 65: | Строка 54: | ||
'''return''' kmin | '''return''' kmin | ||
− | Функция для построения массива <tex>Rmin</tex>. | + | Функция для построения массива <tex>\mathrm{Rmin}</tex>. |
'''int'''[] buildRmin('''int'''[] hmax, '''int'''[] kmin, '''int''' m) | '''int'''[] buildRmin('''int'''[] hmax, '''int'''[] kmin, '''int''' m) | ||
'''int''' rmin[m] | '''int''' rmin[m] | ||
Строка 71: | Строка 60: | ||
'''for''' i = m - 1 .. 0 | '''for''' i = m - 1 .. 0 | ||
'''if''' hmax[i + 1] == m | '''if''' hmax[i + 1] == m | ||
+ | <font color="green">// <tex>r</tex> {{---}} первое число большее, чем <tex>i</tex> и такое, что шаблон имеет период <tex>r</tex></font> | ||
r = i + 1 | r = i + 1 | ||
'''if''' kmin[i] == 0 | '''if''' kmin[i] == 0 | ||
Строка 77: | Строка 67: | ||
rmin[i] = 0 | rmin[i] = 0 | ||
return rmin | return rmin | ||
+ | |||
+ | Функция для построение массива <tex>\mathrm{Shift}</tex>. | ||
+ | '''int'''[] buildShift('''int'''[] kmin, '''int'''[] rmin, '''int'''[] h, '''int''' nd, '''int''' m) | ||
+ | '''int''' shift[m + 1] | ||
+ | '''for''' i = 0 .. nd | ||
+ | shift[i] = kmin[h[i]] | ||
+ | '''for''' i = nd + 1 .. m - 1 | ||
+ | shift[i] = rmin[h[i]] | ||
+ | shift[m] = rmin[0] | ||
+ | '''return''' shift | ||
+ | |||
+ | Функция для построения массива <tex>\mathrm{Next}</tex>. | ||
+ | |||
==Асимптотики== | ==Асимптотики== | ||
Строка 86: | Строка 89: | ||
==Сравнение с другими алгоритмами== | ==Сравнение с другими алгоритмами== | ||
===Достоинства=== | ===Достоинства=== | ||
+ | * Поиск выполняется за <tex>O(n)</tex> в отличие от [[Алгоритм Кнута-Морриса-Пратта|алгоритма Кнута-Морриса-Пратта]], поиск в котором занимается <tex>O(n+m)</tex>, что помогает уменьшить константу при <tex>m~n</tex>. | ||
+ | * Фаза предобработки выполняется за <tex>O(m)</tex> в отличие от [[Алгоритм Бойера-Мура|алгоритма Бойера-Мура]], где в наилучшем случае можно получить время <tex>O(n+|\Sigma|)</tex>, что плохо при больших алфавитах. | ||
===Недостатки=== | ===Недостатки=== | ||
− | == | + | * Сложность реализации. |
+ | ==Источники== | ||
+ | * COLUSSI L., 1991, Correctness and efficiency of the pattern matching algorithms, Information and Computation 95(2):225-251. | ||
* [http://www-igm.univ-mlv.fr/~lecroq/string/node10.html Colussi algorithm] | * [http://www-igm.univ-mlv.fr/~lecroq/string/node10.html Colussi algorithm] | ||
* [http://alg.csie.ncnu.edu.tw/course/StringMatching/Colussi.ppt Colussi.ppt] | * [http://alg.csie.ncnu.edu.tw/course/StringMatching/Colussi.ppt Colussi.ppt] |
Версия 00:58, 15 мая 2014
Содержание
Алгоритм
Отметим, что нумерация символов строк и элементов массива у нас начинается с
.Обозначим префикс-функцию. При этом она должна быть определена для и иметь значение по умолчанию.
Определение: |
Для всех | таких, что выполняется:
Псевдокод
Наивный вариант
int[] buildHmax(char[] x, int m): int hmax[m + 1] for k = 1 .. m int i = k while x[i] == x[i - k] i++ hmax[k] = i return hmax
Явная реализация по определению, очевидно, работает за
и требует памяти.Улучшенный вариант
int[] buildHmax(char[] x, int m): int hmax[m + 1] int i = 1 int k = 1 while k <= m while x[i] == x[i - k] i++; hmax[k] = i int q = k + 1 while hmax[q - k] + k < i hmax[q] = hmax[q - k] + k q++ k = q if k == i + 1 i = k return hmax
На каждой итерации цикла увеличивается либо переменная
, либо (или переменная , которая используется в конечном счете для обновления ). Поскольку и в начале и в конце алгоритма, количество итераций алгоритма не превосходит . Следовательно функция требует времени и памяти.Функция для построения массива
.int[] buildKmin(int[] hmax, int m) int kmin[m] for i = m .. 1 if hmax[i] < m kmin[hmax[i]] = i return kmin
Функция для построения массива
.int[] buildRmin(int[] hmax, int[] kmin, int m) int rmin[m] int r = 0 for i = m - 1 .. 0 if hmax[i + 1] == m //— первое число большее, чем и такое, что шаблон имеет период r = i + 1 if kmin[i] == 0 rmin[i] = r else rmin[i] = 0 return rmin
Функция для построение массива
.int[] buildShift(int[] kmin, int[] rmin, int[] h, int nd, int m) int shift[m + 1] for i = 0 .. nd shift[i] = kmin[h[i]] for i = nd + 1 .. m - 1 shift[i] = rmin[h[i]] shift[m] = rmin[0] return shift
Функция для построения массива
.
Асимптотики
- partitions the set of pattern positions into two disjoint subsets; the positions in the first set are scanned from left to right and when no mismatch occurs the positions of the second subset are scanned from right to left;
- preprocessing phase in time and space complexity;
- searching phase in time complexity;
- performs text character comparisons in the worst case.
Сравнение с другими алгоритмами
Достоинства
- Поиск выполняется за алгоритма Кнута-Морриса-Пратта, поиск в котором занимается , что помогает уменьшить константу при . в отличие от
- Фаза предобработки выполняется за алгоритма Бойера-Мура, где в наилучшем случае можно получить время , что плохо при больших алфавитах. в отличие от
Недостатки
- Сложность реализации.
Источники
- COLUSSI L., 1991, Correctness and efficiency of the pattern matching algorithms, Information and Computation 95(2):225-251.
- Colussi algorithm
- Colussi.ppt