Алгоритм Крочемора — различия между версиями
(→Упрощенный алгоритм) |
|||
Строка 8: | Строка 8: | ||
= Идея = | = Идея = | ||
− | Разобьем описание алгоритма на две части: сначала покажем упрощенный алгоритм, а затем попытаемся его оптимизировать | + | Разобьем описание алгоритма на две части: сначала покажем упрощенный алгоритм, работающий за <tex>O(n^2)</tex>\, а затем попытаемся его оптимизировать до <tex>O(n \cdot log(n))</tex>. |
== Упрощенный алгоритм == | == Упрощенный алгоритм == | ||
Строка 14: | Строка 14: | ||
Рассмотрим следующую строку Фиббоначи: | Рассмотрим следующую строку Фиббоначи: | ||
− | {|style="text-align:center" | + | {|class="wikitable" style="text-align:center" |
+ | |- | ||
|| || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || 10 || 11 || 12 || 13 | || || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || 10 || 11 || 12 || 13 | ||
|- | |- | ||
Строка 20: | Строка 21: | ||
|} | |} | ||
− | Будем вычислять все повторяющиеся подстроки длиной <tex>l</tex>, где <tex>l = 1 ... | + | |
+ | Будем вычислять все повторяющиеся подстроки длиной <tex>l</tex>, где <tex>l = 1 \ldots n - 1</tex>. | ||
+ | Предположим, что в строке <tex>f_6</tex> вычислены последовательности позиций, в которых встречаются одинаковые символы: | ||
+ | {|class="wikitable" style="text-align:center" | ||
+ | |- | ||
+ | |rowspan="2"| <tex>l = 1</tex> || <1, 3, 4, 6, 8, 9, 11, 12> || <2, 5, 7, 10, 13> | ||
+ | |- | ||
+ | || a || b | ||
+ | |} | ||
+ | |||
+ | Если нам заранее известен алфавит и он индексирован, то мы можем выполнить данное вычисление за <tex>O(n)</tex>. | ||
+ | |||
+ | Далее для <tex>l = 2</tex> мы хотим найти все повторяющиеся подстроки длины <tex>2</tex>. Поскольку повторяющиеся подстроки длины <tex>l \geq 2</tex> будут иметь общий префикс длиной <tex>l - 1</tex>, то вычисления уровня <tex>l</tex> должны привести к последовательностям, которые будут подпоследовательностями последовательностей, вычисленных на уровне <tex>l - 1</tex>. Другими словами, разбиение на уровне <tex>l \geq 2</tex> {{---}} декомпозиция разбиения на уровне <tex>l - 1</tex>: | ||
+ | |||
+ | {|class="wikitable" style="text-align:center" | ||
+ | !colspan=6|Последовательная декомпозиция строки <tex>f_6 = abaababaabaab</tex> | ||
+ | |- | ||
+ | | rowspan="2" | <tex>l = 2</tex> || <1, 4, 6, 9, 12> || <3, 8, 11> || <2, 5, 7, 10> || <13> || | ||
+ | |- | ||
+ | || ab || aa || ba || b$ || | ||
+ | |- | ||
+ | | rowspan="2" | <tex>l = 3</tex> || <1, 4, 6, 9> || <12> || <3, 8, 11> || <2, 7, 10> || <5> | ||
+ | |- | ||
+ | || aba || aa$ || aab || baa || bab | ||
+ | |- | ||
+ | | rowspan="2" | <tex>l = 4</tex> || <1, 6, 9> || <4> || <3, 8> || <11> || <2, 7, 10> | ||
+ | |- | ||
+ | || abaa || abab || aaba || aab$ || baab | ||
+ | |- | ||
+ | | rowspan="2" | <tex>l = 5</tex> || <1, 6, 9> || <3> || <8> || <2, 7> || <10> | ||
+ | |- | ||
+ | || abaab || aabab || aabaa || baaba || baab$ | ||
+ | |- | ||
+ | | rowspan="2" | <tex>l = 6</tex> || <1, 6> || <9> || <2> || <7> || | ||
+ | |- | ||
+ | || abaaba || abaab$ || baabab || baabaa || | ||
+ | |- | ||
+ | | rowspan="2" | <tex>l = 7</tex> || <1> || <6> || || || | ||
+ | |- | ||
+ | || abaabab || abaabaa || || || | ||
+ | |} | ||
+ | |||
+ | Если реализовывать процесс декомпозиции "наивно", то поучаем сложность <tex>O(n^2)</tex>. | ||
+ | |||
+ | == Оптимизация == | ||
= Псевдокод = | = Псевдокод = |
Версия 04:03, 28 мая 2014
Определение: |
Тандемным повтором (tandem repeat) в строке называются два вхождения какой-либо подстроки подряд. Иными словами, тандемный повтор описывается парой индексов | такими, что подстрока — это две одинаковые строки, записанные подряд.
Алгоритм Крочемора (Crochemore algorithm) позволяет найти все тандемные повторы в исходной строке за .
Содержание
Идея
Разобьем описание алгоритма на две части: сначала покажем упрощенный алгоритм, работающий за
\, а затем попытаемся его оптимизировать до .Упрощенный алгоритм
Рассмотрим следующую строку Фиббоначи:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | |
a | b | a | a | b | a | b | a | a | b | a | a | b |
Будем вычислять все повторяющиеся подстроки длиной , где .
Предположим, что в строке вычислены последовательности позиций, в которых встречаются одинаковые символы:
<1, 3, 4, 6, 8, 9, 11, 12> | <2, 5, 7, 10, 13> | |
a | b |
Если нам заранее известен алфавит и он индексирован, то мы можем выполнить данное вычисление за
.Далее для
мы хотим найти все повторяющиеся подстроки длины . Поскольку повторяющиеся подстроки длины будут иметь общий префикс длиной , то вычисления уровня должны привести к последовательностям, которые будут подпоследовательностями последовательностей, вычисленных на уровне . Другими словами, разбиение на уровне — декомпозиция разбиения на уровне :Последовательная декомпозиция строки | |||||
---|---|---|---|---|---|
<1, 4, 6, 9, 12> | <3, 8, 11> | <2, 5, 7, 10> | <13> | ||
ab | aa | ba | b$ | ||
<1, 4, 6, 9> | <12> | <3, 8, 11> | <2, 7, 10> | <5> | |
aba | aa$ | aab | baa | bab | |
<1, 6, 9> | <4> | <3, 8> | <11> | <2, 7, 10> | |
abaa | abab | aaba | aab$ | baab | |
<1, 6, 9> | <3> | <8> | <2, 7> | <10> | |
abaab | aabab | aabaa | baaba | baab$ | |
<1, 6> | <9> | <2> | <7> | ||
abaaba | abaab$ | baabab | baabaa | ||
<1> | <6> | ||||
abaabab | abaabaa |
Если реализовывать процесс декомпозиции "наивно", то поучаем сложность
.