@@ -1,34 +1,33 @@
// Given a list of numbers of length n, this routine extracts a
// longest increasing subsequence.
-//
// Running time: O(n log n)
-// INPUT: a vector of integers
-// OUTPUT: a vector containing the longest increasing subsequence
-// #define STRICTLY_INCREASNG // buggué, quand on retrouve la suite ?
-VI LongestIncreasingSubsequence(VI v) {
- VPII best;
- VI dad(v.size(), -1);
- for (int i = 0; i < v.size(); i++) {
-#ifdef STRICTLY_INCREASNG
- PII item = make_pair(v[i], 0);
- VPII::iterator it = lower_bound(best.begin(), best.end(), item);
- item.second = i;
-#else
- PII item = make_pair(v[i], i);
- VPII::iterator it = upper_bound(best.begin(), best.end(), item);
-#endif
- if (it == best.end()) {
- dad[i] = (best.size() == 0 ? -1 : best.back().second);
- best.push_back(item);
- } else {
- dad[i] = dad[it->second];
- *it = item;
- }
- VI ret;
- for (int i = best.back().second; i >= 0; i = dad[i])
- ret.push_back(v[i]);
- reverse(ret.begin(), ret.end());
- return ret;
-}
+int A[MAX_N], indice[MAX_N], back[MAX_N];
+VI lis(VI values, bool strict) {
+ int N = values.size();
+ int k = 0;
+ fill_n(back, N, -1);
+ for(int i = 0; i < N ; i++) {
+ int j;
+ if(strict)
+ j = lower_bound(A, A + k, values[i]) - A;
+ else
+ j = upper_bound(A, A + k, values[i]) - A;
+ if(j == k) {
+ A[k] = values[i];
+ indice[k] = i;
+ ++k;
+ } else if(values[i] < A[j]) {
+ A[j] = values[i];
+ indice[j] = i;
+ }
+ if(i && j && j-1 < k)
+ back[i] = indice[j-1];
+ VI longest(k);
+ int cur = indice[k-1];
+ for(int i = longest.size()-1; i >= 0; i--) {
+ longest[i] = values[cur];
+ cur = back[cur];
+ return longest;
+}
@@ -1,17 +0,0 @@
-#include <bits/stdc++.h>
-using namespace std;
-
-typedef vector<int> VI;
-typedef pair<int, int> PII;
-typedef vector<PII> VPII;
-#include "LongestIncreasingSubsequence.cpp"
-int main() {
- VI v = {1, 2, 3, 4, 7, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
- VI r = LongestIncreasingSubsequence(v);
- for(int i = 0; i < r.size()-1; i++)
- assert(r[i] <= r[i+1]);
- assert(r.size() == 12);
- return 0;
@@ -2,17 +2,28 @@
using namespace std;
typedef vector<int> VI;
+#define MAX_N 1000
-#define STRICTLY_INCREASNG
#include "LongestIncreasingSubsequence.cpp"
+void test1() {
VI v = {3, 4, 7, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-// for(int i = 0; i < r.size()-1; i++)
-// assert(r[i] < r[i+1]);
-// assert(r.size() == 10);
+ VI r = lis(v, true);
+ for(int i = 0; i < r.size()-1; i++)
+ assert(r[i] < r[i+1]);
+ assert(r.size() == 10);
+
+void test2() {
+ VI v = {1, 2, 3, 4, 7, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ VI r = lis(v, false);
+ assert(r[i] <= r[i+1]);
+ assert(r.size() == 12);
}
+int main() {
+ test1();
+ test2();
+ return 0;
@@ -14,10 +14,6 @@ run: $(TEST_RUN)
@echo Compiling $@...
@$(CC) -o $@ $<
-LongestIncreasingSubsequence2_test: LongestIncreasingSubsequence2_test.cpp LongestIncreasingSubsequence.cpp
- @echo Compiling $@...
- @$(CC) -o $@ $<
DiscreteLog_test: DiscreteLog_test.cpp DiscreteLog.cpp Euclid.cpp