Изменения
→Пример алгоритма, работающего за время O(n\cdot\log n)
==== Пример алгоритма, работающего за время <tex> O(n\cdot\log n) </tex> ====
Для строки ''x'' будем по-прежнему хранить массивы <tex>a</tex> (<tex>a</tex> уже длины <tex>n + 1</tex>) и <tex>predprev</tex>, добавим к ним так же массив no <tex>last</tex> из <tex>n + 1 </tex> элементов так, что в no<tex>last[i] </tex> хранится номер последнего элемента в возрастающей подпоследовательности длины <tex>i</tex>. Теперь <tex> a[i] </tex> содержит наименьший по величине элемент, на который может оканчиваться возрастающая подпоследовательность длины <tex>i</tex>, среди всех <tex>x[j]</tex>, где <tex>1 \leqslant j \leqslant i-1 </tex>, если мы на шаге <tex>i</tex>. В свою очередь, pred<tex>prev[i] </tex> хранит индекс предшевствующего символа для наибольшей возрастающей подпоследовательности, оканчивающейся в i-й ой позиции. Заметим, что <tex> a[0] < a[1] < a[2] < \dots < a[n] </tex>. Пусть мы находимся на i-ом шаге, тогда нам надо найти такой номер k <tex> a[k] \leqslant x[i] < a[k+1] </tex> (если положить при начальной реализации <tex> a[0] = -\inf</tex> - фиктивный элемент, <tex>a[1] = a[2] = \dots = a[n] = \inf </tex>, то такое k всегда найдется).Причем если в условии не строгое возрастание, то массив <tex>a</tex> ''не убывает'', и надо искать наибольшее k из возможных. После этого полагаем <tex> a[k + 1] = x[i] </tex>, а остальные элементы массива не меняем. В силу упорядоченности массива a, мы можем искать k бинарным поиском (при не строгом возрастании необходимо пользоваться функцией <tex>upper_bound(1, n, a[i]))</tex>, чтобы найти элемент <tex>a[i]</tex> с максимальным индексом. Параллельно нахождению НВП будем записывать массив предков pred <tex>prev</tex> и номеров no<tex>last</tex>. Подсчитаем время: мы n раз выпоняем бинарный поиск, что требует <tex> O(\log n) </tex> времени. Итого: <tex> O(n\cdot\log n) </tex>.
<code>
lis = 0
a = (n + 1, inf)
a[0] = -inf
For i = 1 to n
j = binary_search(0, n, x[i]) // бинарный поиск j < i, удовлетворяющего x[a[j]] < x[i] и x[i] < x[a[j + 1]]
d[j + 1] = a[i]
p[i] = nolast[j] nolast[j + 1] = i;
If (lis < j + 1)
lis = j + 1;
</code>
Для восстановления самой последовательности необходимой пройти по массиву pred с номера <tex>nolast[lis]</tex>, выводя элементы НВП в обратном порядке, аналогично действиям в прошлом алгоритме.
== Источники ==