Быстрый поиск наибольшей возрастающей подпоследовательности
Алгоритм
Нахождение длины НВП
Основная идея
Пусть
- входная перестановка.Для каждой длины элемент, что может быть последним в возрастающей подпоследовательности длины , запишем их в массив .
предполагаемой НВП находим наименьшийЕсли обрабатываемый элемент
больше последнего элемента какой-нибудь возрастающей последовательности, он может ее увеличить.Будем последовательно обрабатывать элементы
:- Если , значит с ним можно сделать максимальную, из уже рассмотренных, возрастающую подпоследовательность. Записываем его в конец больше
- Иначе становится лучшим элементом для такой длины , что:
Следует отметить, что полученный массив также образует возрастающую последовательность, соответственно целесообразно использовать приоритетную очередь, реализованную через Дерево ван Эмде Боаса. Таким образом получаем амортизированного времени.
Пример
Типы операций:
Последовательность:
9 | 2 | 1 | 3 | 7 | 5 | 6 | 8 | 4 |
Состояние очереди при каждом добавлении:
9 | 9 | ||||
2 | 2 | ||||
1 | 1 | ||||
1 | 3 | 3 | |||
1 | 3 | 7 | 7 | ||
1 | 3 | 5 | 5 | ||
1 | 3 | 5 | 6 | 6 | |
1 | 3 | 5 | 6 | 8 | 8 |
1 | 3 | 4 | 6 | 8 | 4 |
Псевдокод
function LIS( следующий else k = k + 1 // добавляем максимальный - уже добавлен, ничего не удаляем return k[]) B = priorityQueue() k = 0 n = .size for i = 1..n: x = [i] B.insert(x) // в любом случае добавляем в очередь if B.next(x) exists then B.delete(B.next(x)) // удаляем предыдущее значение - заменяем
Расширение алгоритма на нахождение НВП
Основная идея
Будем запоминать пары: для каждого элемента записываем его "предшественника".
Тогда, выбрав какой-нибудь лучший элемент для максимальной длины, мы можем легко восстановить все НВП.
Псевдокод
function LIS([]) B = priorityQueue() k = 0 n = .size <color = 'red'>predecessors = [n]</color> for i = 1 to n x = [i] B.insert(x) predecessor[x] = B.prev(x) if B.next(x) exists then B.delete(B.next(x)) else k = k + 1 result = [] cur = B.max() result += [cur] while predecessor[cur] exists result += [predecessor[cur]] cur = predecessor[cur] return result