Алгоритм Касаи и др. — различия между версиями
(→Псевдокод) |
|||
| Строка 1: | Строка 1: | ||
| + | {| class="wikitable" align="center" style="color: red; background-color: black; font-size: 56px; width: 800px;" | ||
| + | |+ | ||
| + | |-align="center" | ||
| + | |'''НЕТ ВОЙНЕ''' | ||
| + | |-style="font-size: 16px;" | ||
| + | | | ||
| + | 24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян. | ||
| + | |||
| + | Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием. | ||
| + | |||
| + | Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей. | ||
| + | |||
| + | Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить. | ||
| + | |||
| + | ''Антивоенный комитет России'' | ||
| + | |-style="font-size: 16px;" | ||
| + | |Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению. | ||
| + | |-style="font-size: 16px;" | ||
| + | |[https://meduza.io/ meduza.io], [https://www.youtube.com/c/popularpolitics/videos Популярная политика], [https://novayagazeta.ru/ Новая газета], [https://zona.media/ zona.media], [https://www.youtube.com/c/MackNack/videos Майкл Наки]. | ||
| + | |} | ||
| + | |||
'''Алгоритм Касаи, Аримуры, Арикавы, Ли, Парка''' (англ. ''Kasai, Arimura, Arikawa, Lee, Park algorithm'') {{---}} алгоритм, позволяющий за линейное время вычислить длину наибольших общих префиксов (англ. ''longest common prefix'', ''LCP'') для всех соседних суффиксов строки, отсортированных в лексикографическом порядке. | '''Алгоритм Касаи, Аримуры, Арикавы, Ли, Парка''' (англ. ''Kasai, Arimura, Arikawa, Lee, Park algorithm'') {{---}} алгоритм, позволяющий за линейное время вычислить длину наибольших общих префиксов (англ. ''longest common prefix'', ''LCP'') для всех соседних суффиксов строки, отсортированных в лексикографическом порядке. | ||
Версия 07:05, 1 сентября 2022
| НЕТ ВОЙНЕ |
|
24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян. Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием. Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей. Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить. Антивоенный комитет России |
| Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению. |
| meduza.io, Популярная политика, Новая газета, zona.media, Майкл Наки. |
Алгоритм Касаи, Аримуры, Арикавы, Ли, Парка (англ. Kasai, Arimura, Arikawa, Lee, Park algorithm) — алгоритм, позволяющий за линейное время вычислить длину наибольших общих префиксов (англ. longest common prefix, LCP) для всех соседних суффиксов строки, отсортированных в лексикографическом порядке.
Содержание
Обозначения
Введём следующие обозначения:
- — данная строка.
- — суффикс строки , начинающийся в -ом символе.
- — суффиксный массив.
- — массив, обратный суффиксному, который может быть получен немедленно, если задан массив . Если , то .
- — длина наибольшего общего префикса строк и .
- — длина наибольшего общего префикса соседних строк и , то есть .
Некоторые свойства LCP
| Утверждение (№1): |
|
между двумя суффиксами — минимум всех пар соседних суффиксов между ними в суффиксном массиве . То есть . Отсюда следует, что пары соседних суффиксов в массиве больше или равно пары суффиксов, окружающих их. |
Также заметим, что .
| Утверждение (№2): |
Если , тогда |
| Рассмотрим пару суффиксов, соседних в массиве . Тогда если их значение больше , то можно удалить первый символ этих суффиксов и их лексикографический порядок относительно друг друга сохранится. То есть строка будет идти следом за строкой и останется лексикографически больше нее. |
| Утверждение (№3): |
Если , тогда |
| В этом же случае, значение между и на один меньше значения между и . |
Пример
Рассмотрим строку . Её суффиксный массив:
Распишем суффиксный массив по столбикам для удобного нахождения :
Строим массив :
Например — длина наибольшего общего префикса суффиксов и .
Вспомогательные утверждения
Теперь рассмотрим следующую задачу: рассчитать между суффиксом и его соседним суффиксом в массиве , при условии, что значение между и его соседним суффиксом известны. Для удобства записи пусть и . Так же пусть и . Проще говоря, мы хотим посчитать , когда задано .
| Лемма: |
Если , тогда . |
| Доказательство: |
| Так как , имеем из утверждения №2. Так как , имеем из утверждения №1. |
| Теорема: |
Если , то |
| Доказательство: |
|
(по лемме). (по утверждению №3). Значит, . |
Алгоритм
Представим алгоритм который вычисляет массив , зная суффиксный массив. Исходя из выше написанной теоремы, нам не нужно сравнивать все символы, когда мы вычисляем между суффиксом и его соседним суффиксом в массиве . Чтобы вычислить всех соседних суффиксов в массиве эффективно, будем рассматривать суффиксы по порядку начиная с и заканчивая .
Псевдокод
Алгоритм принимает на вход строку длиной , с добавленным специальным символом и суффиксный массив этой строки, и возвращает массив .
int[] buildLCP(str: string, suf: int[]) int n str.length int[len] lcp int[len] pos // pos[] — массив, обратный массиву suf for i = 0 to n - 1 pos[suf[i]] i int k 0 for i = 0 to n - 1 if k > 0 k-- if pos[i] == n - 1 lcp[n - 1] -1 k 0 continue else int j suf[pos[i] + 1] while max(i + k, j + k) < n and str[i + k] == str[j + k] k++ lcp[pos[i]] k return lcp
Асимптотика
Таким образом, начиная проверять для текущего суффикса не с первого символа, а с указанного, можно за линейное время построить . Покажем, что построение таким образом действительно требует времени. Действительно, на каждой итерации текущее значение может быть не более чем на единицу меньше предыдущего. Таким образом, значения в сумме могут увеличиться не более, чем на (с точностью до константы). Следовательно, алгоритм построит за .