Быстрый поиск наибольшей возрастающей подпоследовательности — различия между версиями
м (→Обработка блока: Дополнение про predecessor) |
м (Тире, to, dfrac, radix interwiki, точки, geqslant, неясность некоторых формулировок, tex в заголовках, см также, источники, категории) |
||
Строка 6: | Строка 6: | ||
[[Файл:Task.jpg]] | [[Файл:Task.jpg]] | ||
− | == Алгоритм | + | == Алгоритм O(n log log n) == |
=== Нахождение длины НВП === | === Нахождение длины НВП === | ||
==== Основная идея ==== | ==== Основная идея ==== | ||
Строка 17: | Строка 17: | ||
Будем последовательно обрабатывать элементы <tex>\pi(1), \pi(2),~\dots,~\pi(n)</tex>: | Будем последовательно обрабатывать элементы <tex>\pi(1), \pi(2),~\dots,~\pi(n)</tex>: | ||
− | * Если <tex>\pi(i)</tex> больше {{Acronym | <tex>\pi(1), \pi(2),~\dots~,\pi(i-1)</tex> | всех уже полученных значений B }}, значит с ним можно сделать максимальную, из уже рассмотренных, возрастающую подпоследовательность. Записываем его в конец <tex>B</tex> | + | * Если <tex>\pi(i)</tex> больше {{Acronym | <tex>\pi(1), \pi(2),~\dots~,\pi(i-1)</tex> | всех уже полученных значений B }}, значит с ним можно сделать максимальную, из уже рассмотренных, возрастающую подпоследовательность. Записываем его в конец <tex>B</tex>. |
* Иначе <tex>\pi(i)</tex> заменяет наименьший лучший элемент, из тех, что больше <tex>\pi(i)</tex>. | * Иначе <tex>\pi(i)</tex> заменяет наименьший лучший элемент, из тех, что больше <tex>\pi(i)</tex>. | ||
Строка 71: | Строка 71: | ||
'''int''' k = 0 <font color=darkgreen>// длина НВП</font> | '''int''' k = 0 <font color=darkgreen>// длина НВП</font> | ||
'''int''' n = <tex>\pi</tex>.size | '''int''' n = <tex>\pi</tex>.size | ||
− | '''for''' i = 1 to n | + | '''for''' i = 1 '''to''' n |
x = <tex>\pi</tex>[i] | x = <tex>\pi</tex>[i] | ||
<font color=darkgreen>// в любом случае добавляем в очередь очередной элемент</font> | <font color=darkgreen>// в любом случае добавляем в очередь очередной элемент</font> | ||
Строка 81: | Строка 81: | ||
B.delete(B.next(x)) | B.delete(B.next(x)) | ||
'''else''' | '''else''' | ||
− | <font color=darkgreen>// добавленный элемент | + | <font color=darkgreen>// добавленный элемент — максимальный</font> |
<font color=darkgreen>// предыдущие значения не трогаем, очередь увеличилась</font> | <font color=darkgreen>// предыдущие значения не трогаем, очередь увеличилась</font> | ||
k = k + 1 | k = k + 1 | ||
Строка 137: | Строка 137: | ||
'''int''' n = <tex>\pi</tex>.size | '''int''' n = <tex>\pi</tex>.size | ||
<font color=blue>'''vector<int>''' predecessor(n)</font> <font color=darkgreen>// резервируем <tex>n</tex> позиций</font> | <font color=blue>'''vector<int>''' predecessor(n)</font> <font color=darkgreen>// резервируем <tex>n</tex> позиций</font> | ||
− | '''for''' i = 1 to n | + | '''for''' i = 1 '''to''' n |
x = <tex>\pi</tex>[i] | x = <tex>\pi</tex>[i] | ||
B.insert(x) | B.insert(x) | ||
Строка 155: | Строка 155: | ||
'''return''' result</font> | '''return''' result</font> | ||
</code> | </code> | ||
− | == Оптимизация до | + | == Оптимизация до O(n log log k)</tex> == |
=== Основная идея === | === Основная идея === | ||
Чтобы [[Дерево ван Эмде Боаса]] выполняло операции за <tex>O(\operatorname{log}\operatorname{log}k)</tex>, необходимо алфавит обрабатываемых значений уменьшить до <tex>O(k)</tex>. | Чтобы [[Дерево ван Эмде Боаса]] выполняло операции за <tex>O(\operatorname{log}\operatorname{log}k)</tex>, необходимо алфавит обрабатываемых значений уменьшить до <tex>O(k)</tex>. | ||
− | Предположим, мы знаем такое {{Acronym|приближение <tex>k</tex>|далее рассмотрим нахождение и насколько оно точное}} <tex>m: m \ | + | Предположим, мы знаем такое {{Acronym|приближение числа <tex>k</tex>|далее рассмотрим нахождение и насколько оно точное}} числом <tex>m: m \geqslant k</tex>. Если мы разобьем всю последовательность на блоки из {{ Acronym|<tex>m</tex> элементов|последний блок может быть меньше}} и нам удастся обрабатывать каждый как перестановку из <tex>m</tex> элементов, то мы получим асимптотическое время <tex>O(n \operatorname{log} \operatorname{log} (k + m))</tex>, а т.к. <tex>m \geqslant k</tex>, то <tex>O(n \operatorname{log} \operatorname{log} m)</tex>. (Мы будем обрабатывать блоки последовательно, т.е. с предыдущего блока у нас может остаться <tex>k</tex> значений в очереди, которые дополняются <tex>m</tex> значениями очередного блока — получаем верхнее ограничение в <tex>k + m</tex> обрабатываемых возможных значений.) |
'''''Описанный здесь алгоритм подбора <tex>m_i</tex> и получение асимптотической оценки <tex>O(n\operatorname{log}\operatorname{log}k)</tex> в других подразделах рассмотрено не будет, т.к. в основном это доказательство, сложного для понимания/реализации ничего нет''''' | '''''Описанный здесь алгоритм подбора <tex>m_i</tex> и получение асимптотической оценки <tex>O(n\operatorname{log}\operatorname{log}k)</tex> в других подразделах рассмотрено не будет, т.к. в основном это доказательство, сложного для понимания/реализации ничего нет''''' | ||
− | Рассмотрим последовательность <tex>\{m_0,~m_1,~m_2,~\dots\}</tex>, где <tex> m_{i+1} = m_i ^{\operatorname{log}m_i} = 2^{\operatorname{log}^2m_i}</tex>, <tex>m_0</tex> | + | Рассмотрим последовательность <tex>\{m_0,~m_1,~m_2,~\dots\}</tex>, где <tex> m_{i+1} = m_i ^{\operatorname{log}m_i} = 2^{\operatorname{log}^2m_i}</tex>, <tex>m_0</tex> — некоторое значение, меньшее <tex>k</tex>. |
− | Будем последовательно для элементов этой последовательности запускать {{Acronym|алгоритм|о котором ниже}}. Если условие <tex>m \ | + | Будем последовательно для элементов этой последовательности запускать {{Acronym|алгоритм|о котором ниже}}. Если условие <tex>m \geqslant k</tex> перестает выполняться, прерываем выполнение. Таким образом, время работы для каждого <tex>m_j</tex> будет <tex>O(n\operatorname{log}\operatorname{log}m_j)</tex>. {{Acronym|Найдется|первый из подобных}} такой <tex>m_i</tex>, который окажется больше <tex>k</tex>, и алгоритм успешно завершится. |
<tex>\operatorname{log}\operatorname{log}m_{i+1} = \operatorname{log}\operatorname{log}2^{\operatorname{log}^2m_i} = \operatorname{log}\operatorname{log}^2m_i = 2\operatorname{log}\operatorname{log}m_i</tex> | <tex>\operatorname{log}\operatorname{log}m_{i+1} = \operatorname{log}\operatorname{log}2^{\operatorname{log}^2m_i} = \operatorname{log}\operatorname{log}^2m_i = 2\operatorname{log}\operatorname{log}m_i</tex> | ||
Строка 171: | Строка 171: | ||
<tex>\operatorname{log}\operatorname{log}m_j = 2^{j-i}\operatorname{log}\operatorname{log}m_i</tex> | <tex>\operatorname{log}\operatorname{log}m_j = 2^{j-i}\operatorname{log}\operatorname{log}m_i</tex> | ||
− | {{Acronym|Общее время|для всех обработанных значений m}} работы | + | {{Acronym|Общее время|для всех обработанных значений m}} работы — <tex>O(n(\sum\limits_{j = 0}\limits^{i}2^{1-j})\operatorname{log}\operatorname{log}m_i) = O(n\operatorname{log}\operatorname{log}m_i)</tex>. Заметим, что <tex>m_i < k^{\operatorname{log}k}</tex>, т.к. в противном случае <tex>m_{i-1} > k</tex>, что противоречит тому, что <tex>m_i</tex> — первый из тех, что больше <tex>k</tex>. Следовательно, <tex>\operatorname{log}\operatorname{log}m_i < 2\operatorname{log}\operatorname{log}k \</tex>. |
− | Получаем время работы <tex>O(n\operatorname{log}\operatorname{log}k)</tex> | + | Получаем время работы <tex>O(n\operatorname{log}\operatorname{log}k)</tex>. |
=== Деление на блоки === | === Деление на блоки === | ||
==== Основная идея ==== | ==== Основная идея ==== | ||
Разделим исходную перестановку <tex>\pi</tex> на блоки <tex>C_j = \{\pi_{(j-1)m + 1},~\pi_{(j-1)m + 2},~\dots, ~\pi_{(j-1)m + m}\}</tex>. | Разделим исходную перестановку <tex>\pi</tex> на блоки <tex>C_j = \{\pi_{(j-1)m + 1},~\pi_{(j-1)m + 2},~\dots, ~\pi_{(j-1)m + m}\}</tex>. | ||
− | Получим сортированные варианты этих блоков <tex>C_j^S</tex>. | + | Получим сортированные варианты этих блоков <tex>C_j^S</tex>. Лобовая [[цифровая сортировка]] дает нам время работы <tex>O(\dfrac{n}{m}n)</tex>. Дополним каждый элемент <tex>\pi</tex> номером блока, в котором он находится и смещением в этом блоке. Теперь, {{Acronym|рассматривая номер блока как старший разряд, элемент как младший разряд|по смещению внутри блока не сортируем}}, можно сортировать цифровой сортировкой за линейное время <tex>O(n)</tex>. |
− | Перестановка смещений, образованная в сортированном блоке есть не что иное, как обратная перестановка перестановки, элементы которой соотносятся между собой как элементы исходного блока. Находим обратную перестановку к найденной, назовем ее <tex>\xi</tex> | + | Перестановка смещений, образованная в сортированном блоке есть не что иное, как обратная перестановка перестановки, элементы которой соотносятся между собой как элементы исходного блока. Находим обратную перестановку к найденной, назовем ее <tex>\xi</tex>. |
==== Пример ==== | ==== Пример ==== | ||
Пусть <tex>m = 5</tex>. Исходно: | Пусть <tex>m = 5</tex>. Исходно: | ||
Строка 209: | Строка 209: | ||
=== Обработка блока === | === Обработка блока === | ||
==== Основная идея ==== | ==== Основная идея ==== | ||
− | * {{Acronym|Достаем из очереди ключи|если это первый блок | + | * {{Acronym|Достаем из очереди ключи|если это первый блок — ничего не делаем}} и конвертируем их в элементы <tex>\pi</tex>. |
* Классический [[Сортировка слиянием#Принцип работы#Слияние двух массивов | merge]] только что полученных элементов <tex>\pi</tex> с элементами нового блока, но с модификацией: генерируются 2 дополнительных массива - индексы элементов исходных массивов в новом. Слияние массивов назовем <tex>merged</tex>. | * Классический [[Сортировка слиянием#Принцип работы#Слияние двух массивов | merge]] только что полученных элементов <tex>\pi</tex> с элементами нового блока, но с модификацией: генерируются 2 дополнительных массива - индексы элементов исходных массивов в новом. Слияние массивов назовем <tex>merged</tex>. | ||
Строка 215: | Строка 215: | ||
* На массив индексов, относящиеся к новому блоку, действует перестановка смещений сортированного варианта этого блока. Таким образом мы добиваемся эквиваленции отношений {{Acronym|ключей|смещений}} к отношениям элементов в очереди и элементов в блоке, а ключи находятся в диапазоне <tex>O(m)</tex>. | * На массив индексов, относящиеся к новому блоку, действует перестановка смещений сортированного варианта этого блока. Таким образом мы добиваемся эквиваленции отношений {{Acronym|ключей|смещений}} к отношениям элементов в очереди и элементов в блоке, а ключи находятся в диапазоне <tex>O(m)</tex>. | ||
− | * Первый массив индексов, который соответствует элементам, ранее находящимся в очереди, вновь кладутся в очередь (обычными <tex>insert</tex>-ами). Второй массив обрабатывается описанным выше алгоритмом <tex>LIS</tex>, при том массив <tex>predecessor</tex> строится из ключей с помощью <tex>merged</tex> | + | * Первый массив индексов, который соответствует элементам, ранее находящимся в очереди, вновь кладутся в очередь (обычными <tex>insert</tex>-ами). Второй массив обрабатывается описанным выше алгоритмом <tex>LIS</tex>, при том массив <tex>predecessor</tex> строится из ключей с помощью <tex>merged</tex>. |
==== Визуализация ==== | ==== Визуализация ==== | ||
− | Помеченные <font color=green>зеленым</font> | + | Помеченные <font color=green>зеленым</font> — условные данные. Остальное — условные операции. Например <tex>keys \longrightarrow merged</tex> значит взять элементы из массива <tex>merged</tex> c индексами из <tex>keys</tex>. <tex>merge \longrightarrow merged</tex> — здесь <tex>merged</tex> обозначает результат операции '''merge'''. |
[[Файл:blockHandle.jpg]] | [[Файл:blockHandle.jpg]] | ||
Строка 274: | Строка 274: | ||
<tex>merged: \{3, 4, 8, 9, 10\}</tex> | <tex>merged: \{3, 4, 8, 9, 10\}</tex> | ||
===== Второй блок ===== | ===== Второй блок ===== | ||
− | Восстанавливаем элементы <tex>B: \{1, 2, 3\}</tex> из <tex>merged: \{3, 4, 8, 9, 10\}</tex>: <tex>\{3, 4, 8\}</tex> | + | Восстанавливаем элементы <tex>B: \{1, 2, 3\}</tex> из <tex>merged: \{3, 4, 8, 9, 10\}</tex>: <tex>\{3, 4, 8\}</tex>. |
{| | {| | ||
| || | | || | ||
Строка 305: | Строка 305: | ||
{| class="wikitable" style="center" | {| class="wikitable" style="center" | ||
|-align="center" | |-align="center" | ||
− | | colspan="3"|<tex>ind's\#0</tex> | + | | colspan="3"|<tex>ind's\#0</tex> — индексы текущих |
|-align="center" | |-align="center" | ||
| 3||4||7 | | 3||4||7 | ||
Строка 312: | Строка 312: | ||
{| class="wikitable" style="center" | {| class="wikitable" style="center" | ||
|-align="center" | |-align="center" | ||
− | | colspan="5"|<tex>ind's\#1</tex> | + | | colspan="5"|<tex>ind's\#1</tex> — индексы новых |
|-align="center" | |-align="center" | ||
| 1||2||5||6||8 | | 1||2||5||6||8 | ||
Строка 363: | Строка 363: | ||
===== Третий блок ===== | ===== Третий блок ===== | ||
− | Восстанавливаем элементы <tex>B: \{1, 2, 5, 8\}</tex> из <tex>merged: \{1,2,3,4,5,6,8,12\}</tex>: <tex>\{1, 2, 5, 12\}</tex> | + | Восстанавливаем элементы <tex>B: \{1, 2, 5, 8\}</tex> из <tex>merged: \{1,2,3,4,5,6,8,12\}</tex>: <tex>\{1, 2, 5, 12\}</tex>. |
{| | {| | ||
| || | | || | ||
Строка 394: | Строка 394: | ||
{| class="wikitable" style="center" | {| class="wikitable" style="center" | ||
|-align="center" | |-align="center" | ||
− | | colspan="4"|<tex>ind's\#0</tex> | + | | colspan="4"|<tex>ind's\#0</tex> — индексы текущих |
|-align="center" | |-align="center" | ||
| 1||2||3||6 | | 1||2||3||6 | ||
Строка 401: | Строка 401: | ||
{| class="wikitable" style="center" | {| class="wikitable" style="center" | ||
|-align="center" | |-align="center" | ||
− | | colspan="2"|<tex>ind's\#1</tex> | + | | colspan="2"|<tex>ind's\#1</tex> — индексы новых |
|-align="center" | |-align="center" | ||
| 4||5 | | 4||5 | ||
Строка 463: | Строка 463: | ||
| 1||2||5||7||11 | | 1||2||5||7||11 | ||
|} | |} | ||
+ | == См. также == | ||
+ | *[[Дерево ван Эмде Боаса]] | ||
+ | *[[Задача о наибольшей возрастающей подпоследовательности]] | ||
+ | *[[Задача о наибольшей общей подпоследовательности]] | ||
+ | *[[Наибольшая общая возрастающая подпоследовательность]] | ||
+ | *[[Задача о наибольшей общей палиндромной подпоследовательности]] | ||
+ | |||
+ | == Источники информации == | ||
+ | * [http://www.bcs.org/upload/pdf/ewic_vs08_s2paper2.pdf] (07.01.2017) | ||
+ | |||
+ | [[Категория: Дискретная математика и алгоритмы]] | ||
+ | [[Категория: Динамическое программирование]] |
Версия 22:25, 7 января 2017
Задача: |
Дана перестановка . Требуется найти НВП за , где — длина НВП. |
Содержание
Алгоритм O(n log log n)
Нахождение длины НВП
Основная идея
Пусть
— входная перестановка.Для каждой длины элемент, что может быть последним в возрастающей подпоследовательности длины , запишем их в массив .
предполагаемой НВП находим наименьшийЕсли обрабатываемый элемент
больше последнего элемента какой-нибудь возрастающей последовательности, он может ее увеличить.Будем последовательно обрабатывать элементы
:- Если , значит с ним можно сделать максимальную, из уже рассмотренных, возрастающую подпоследовательность. Записываем его в конец . больше
- Иначе заменяет наименьший лучший элемент, из тех, что больше .
Следует отметить, что полученный массив также образует возрастающую последовательность, где мы должны выполнять операции приоритетную очередь, реализованную через Дерево ван Эмде Боаса. Таким образом получаем амортизированного времени на одну операцию.
, соответственно целесообразно использоватьПример
Типы операций:
Последовательность:
9 | 3 | 10 | 4 | 8 | 1 | 2 | 12 | 6 | 5 | 7 | 11 |
Состояние очереди при каждом добавлении:
9 | 9 | ||||
3 | 3 | ||||
3 | 10 | 10 | |||
3 | 4 | 4 | |||
3 | 4 | 8 | 8 | ||
1 | 4 | 8 | 1 | ||
1 | 2 | 8 | 2 | ||
1 | 2 | 8 | 12 | 12 | |
1 | 2 | 6 | 12 | 6 | |
1 | 2 | 5 | 12 | 5 | |
1 | 2 | 5 | 7 | 7 | |
1 | 2 | 5 | 7 | 11 | 11 |
Псевдокод
int LIS(vector<int> следующий B.delete(B.next(x)) else // добавленный элемент — максимальный // предыдущие значения не трогаем, очередь увеличилась k = k + 1 return k) PriorityQueue B // рабочая приоритетная очередь int k = 0 // длина НВП int n = .size for i = 1 to n x = [i] // в любом случае добавляем в очередь очередной элемент // устаревшие будем удалять B.insert(x) if B.next(x) // добавленный элемент — не максимальный // удаляем предыдущее значение — заменяем
Расширение алгоритма до нахождения НВП
Основная идея
Будем запоминать пары: для каждого элемента записываем его "предшественника".
Тогда, выбрав какой-нибудь лучший элемент для максимальной длины, мы можем легко восстановить НВП .
Общий вид алгоритма
9 | 9 | ||||
3 | 3 | ||||
3 | 10 | 10 | |||
3 | 4 | 4 | |||
3 | 4 | 8 | 8 | ||
1 | 4 | 8 | 1 | ||
1 | 2 | 8 | 2 | ||
1 | 2 | 8 | 12 | 12 | |
1 | 2 | 6 | 12 | 6 | |
1 | 2 | 5 | 12 | 5 | |
1 | 2 | 5 | 7 | 7 | |
1 | 2 | 5 | 7 | 11 | 11 |
predecessor | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
1 | 3 | 2 | 2 | 5 | 4 | 3 | 7 | 8 |
Псевдокод
vector<int> LIS(vector<int>) PriorityQueue B int k = 0 int n = .size vector<int> predecessor(n) // резервируем позиций for i = 1 to n x = [i] B.insert(x) predecessor[x] = B.prev(x) if B.next(x) B.delete(B.next(x)) else k = k + 1 // по цепочке от последнего элемента // восстанавливаем НВП vector<int> result int cur = B.max() result += [cur] while predecessor[cur] result += [predecessor[cur]] cur = predecessor[cur] return result
Оптимизация до O(n log log k)</tex>
Основная идея
Чтобы Дерево ван Эмде Боаса выполняло операции за , необходимо алфавит обрабатываемых значений уменьшить до .
Предположим, мы знаем такое приближение числа числом . Если мы разобьем всю последовательность на блоки из и нам удастся обрабатывать каждый как перестановку из элементов элементов, то мы получим асимптотическое время , а т.к. , то . (Мы будем обрабатывать блоки последовательно, т.е. с предыдущего блока у нас может остаться значений в очереди, которые дополняются значениями очередного блока — получаем верхнее ограничение в обрабатываемых возможных значений.)
Описанный здесь алгоритм подбора
и получение асимптотической оценки в других подразделах рассмотрено не будет, т.к. в основном это доказательство, сложного для понимания/реализации ничего нетРассмотрим последовательность
, где , — некоторое значение, меньшее .Будем последовательно для элементов этой последовательности запускать алгоритм. Если условие перестает выполняться, прерываем выполнение. Таким образом, время работы для каждого будет . Найдется такой , который окажется больше , и алгоритм успешно завершится.
Общее время работы — . Заметим, что , т.к. в противном случае , что противоречит тому, что — первый из тех, что больше . Следовательно, .
Получаем время работы
.Деление на блоки
Основная идея
Разделим исходную перестановку
на блоки .Получим сортированные варианты этих блоков цифровая сортировка дает нам время работы . Дополним каждый элемент номером блока, в котором он находится и смещением в этом блоке. Теперь, рассматривая номер блока как старший разряд, элемент как младший разряд, можно сортировать цифровой сортировкой за линейное время .
. ЛобоваяПерестановка смещений, образованная в сортированном блоке есть не что иное, как обратная перестановка перестановки, элементы которой соотносятся между собой как элементы исходного блока. Находим обратную перестановку к найденной, назовем ее
.Пример
Пусть
. Исходно:Блок | 1 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 3 | 3 |
9 | 3 | 10 | 4 | 8 | 1 | 2 | 12 | 6 | 5 | 7 | 11 | |
Смещение | 1 | 2 | 3 | 4 | 5 | 1 | 2 | 3 | 4 | 5 | 1 | 2 |
После сортировки:
Блок | 1 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 3 | 3 |
3 | 4 | 8 | 9 | 10 | 1 | 2 | 5 | 6 | 12 | 7 | 11 | |
Смещение | 2 | 4 | 5 | 1 | 3 | 1 | 2 | 5 | 4 | 3 | 1 | 2 |
Обратные перестановки (
):1 | 2 | 3 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
4 | 1 | 5 | 2 | 3 | 1 | 2 | 5 | 4 | 3 | 1 | 2 |
Обработка блока
Основная идея
- Достаем из очереди ключи и конвертируем их в элементы .
- Классический merge только что полученных элементов с элементами нового блока, но с модификацией: генерируются 2 дополнительных массива - индексы элементов исходных массивов в новом. Слияние массивов назовем .
- На массив индексов, относящиеся к новому блоку, действует перестановка смещений сортированного варианта этого блока. Таким образом мы добиваемся эквиваленции отношений ключей к отношениям элементов в очереди и элементов в блоке, а ключи находятся в диапазоне .
- Первый массив индексов, который соответствует элементам, ранее находящимся в очереди, вновь кладутся в очередь (обычными -ами). Второй массив обрабатывается описанным выше алгоритмом , при том массив строится из ключей с помощью .
Визуализация
Помеченные зеленым — условные данные. Остальное — условные операции. Например
значит взять элементы из массива c индексами из . — здесь обозначает результат операции merge.Для первого блока содержательным является лишь ветка, начинающаяся с
, что не противоречит представленной схеме.Пример
Первый блок
|
|
аналогичен сортированному, т.к. предыдущих ключей нет.
Ключи сортированного блока | ||||
---|---|---|---|---|
2 | 4 | 5 | 1 | 3 |
4 | 1 | 5 | 2 | 3 |
Пропускаем их через
:4 | 4 | ||
1 | 1 | ||
1 | 5 | 5 | |
1 | 2 | 2 | |
1 | 2 | 3 | 3 |
Результат работы
Второй блок
Восстанавливаем элементы
из : .
|
|
|
|
|
Ключи сортированного блока | ||||
---|---|---|---|---|
1 | 2 | 5 | 4 | 3 |
1 | 2 | 5 | 4 | 3 |
Восстанавливаем порядок новых из
и :новые ключи | ||||
---|---|---|---|---|
1 | 2 | 8 | 6 | 5 |
Обновление старых ключей:
3 | 3 | ||
3 | 4 | 4 | |
3 | 4 | 7 | 7 |
новых:
1 | 4 | 7 | 1 | |
1 | 2 | 7 | 2 | |
1 | 2 | 7 | 8 | 8 |
1 | 2 | 6 | 8 | 6 |
1 | 2 | 5 | 8 | 5 |
Результат работы
Третий блок
Восстанавливаем элементы
из : .
|
|
|
|
|
Ключи сортированного блока | ||||
---|---|---|---|---|
1 | 2 |
1 | 2 |
Восстанавливаем порядок новых из
и :новые ключи | |
---|---|
4 | 5 |
Обновление старых ключей:
1 | 4 | 7 | 1 | |
1 | 2 | 7 | 2 | |
1 | 2 | 3 | 3 | |
1 | 2 | 3 | 6 | 6 |
новых:
1 | 2 | 3 | 4 | 4 | |
1 | 2 | 3 | 4 | 5 | 5 |
Результат работы
Восстановление НВП
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
1 | 3 | 2 | 2 | 5 | 4 | 3 | 7 | 8 |
Начинаем восстановление с
:11 | 7 | 5 | 2 | 1 |
1 | 2 | 5 | 7 | 11 |
См. также
- Дерево ван Эмде Боаса
- Задача о наибольшей возрастающей подпоследовательности
- Задача о наибольшей общей подпоследовательности
- Наибольшая общая возрастающая подпоследовательность
- Задача о наибольшей общей палиндромной подпоследовательности
Источники информации
- [1] (07.01.2017)