Алгоритм Крочемора — различия между версиями
Строка 4: | Строка 4: | ||
}} | }} | ||
− | '''Алгоритм Крочемора''' (Crochemore algorithm) позволяет найти все тандемные повторы в исходной строке <tex>s[1..n]</tex> за <tex>O(n \cdot log (n))</tex> | + | '''Алгоритм Крочемора''' (Crochemore algorithm) позволяет найти все тандемные повторы в исходной строке <tex>s[1..n]</tex> за <tex>O(n \cdot log (n))</tex> |
= Идея = | = Идея = | ||
− | Разобьем описание алгоритма на две части: сначала покажем упрощенный алгоритм, работающий за <tex>O(n^2)</tex>\, а затем попытаемся его оптимизировать до <tex>O(n \cdot log(n))</tex> | + | Разобьем описание алгоритма на две части: сначала покажем упрощенный алгоритм, работающий за <tex>O(n^2)</tex>\, а затем попытаемся его оптимизировать до <tex>O(n \cdot log(n))</tex> |
== Упрощенный алгоритм == | == Упрощенный алгоритм == | ||
Строка 63: | Строка 63: | ||
|} | |} | ||
− | Если реализовывать процесс декомпозиции "наивно", то поучаем сложность <tex>O(n^2)</tex> | + | Если реализовывать процесс декомпозиции "наивно", то поучаем сложность <tex>O(n^2)</tex> |
== Оптимизация == | == Оптимизация == | ||
+ | |||
+ | Декомпозицию каждой последовательности можно получить косвенным путем, а не путем прямых вычислений. Идея такого подхода состоит в следующем: | ||
+ | на каждом уровне <tex>l</tex> выполняется непосредственная декомпозиция каждой последовательности <tex>c^{(l)}_j</tex>. Более точно, если <tex>c^{(l)}_j = <p_1, p_2, \ldots , p_r></tex>, то необходимо проверить совпадение букв <tex>s[p_1 + l], s[p_2 + l], \ldots, s[p_r + l]</tex>, и, если какие-либо пары букв <tex>s[p_i + l]</tex> и <tex>s[p_j + l]</tex> равны, то <tex>p_i</tex> и <tex>p_j</tex> помещаются в одну и ту же последовательность на уровне <tex>l + 1</tex>. | ||
+ | |||
+ | |||
+ | В приведенном выше примере для строки <tex>f_6</tex> последовательность <tex><1, 4, 6, 9></tex> на уровне <tex>3</tex> разбивается на уровне <tex>4</tex> на последовательности <tex><1, 6, 9></tex> и <tex><4></tex>, поскольку | ||
+ | <tex>f_6[1 + 3] = f_6[6 + 3] = f_6[9 + 3] \neq f_6[4 + ]</tex>. | ||
+ | |||
+ | |||
+ | Но декомпозицию можно выполнить, основываясь не на разбиваемой последовательности, а на последовательностях, относительно которых будут разбиваться другие последовательности. Снова рассмотрим уровень <tex>l = </tex> и последовательность | ||
+ | <tex>c^{(3)}_1 = <p_1, p_2, p_3, p_4> = <1, 4, 6, 9></tex>, | ||
+ | относящуюся к подстроке <tex>aba</tex>. | ||
+ | |||
+ | |||
+ | |||
= Псевдокод = | = Псевдокод = |
Версия 04:35, 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 |
Если реализовывать процесс декомпозиции "наивно", то поучаем сложность
Оптимизация
Декомпозицию каждой последовательности можно получить косвенным путем, а не путем прямых вычислений. Идея такого подхода состоит в следующем: на каждом уровне
выполняется непосредственная декомпозиция каждой последовательности . Более точно, если , то необходимо проверить совпадение букв , и, если какие-либо пары букв и равны, то и помещаются в одну и ту же последовательность на уровне .
В приведенном выше примере для строки последовательность на уровне разбивается на уровне на последовательности и , поскольку
.
Но декомпозицию можно выполнить, основываясь не на разбиваемой последовательности, а на последовательностях, относительно которых будут разбиваться другие последовательности. Снова рассмотрим уровень и последовательность
,
относящуюся к подстроке .