Browse Source

change LIS

Olivier Marty 8 years ago
parent
commit
67cff0ec70

+ 30 - 31
code/LongestIncreasingSubsequence.cpp

@@ -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;
+}

+ 0 - 17
code/LongestIncreasingSubsequence2_test.cpp

@@ -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;
-}

+ 20 - 9
code/LongestIncreasingSubsequence_test.cpp

@@ -2,17 +2,28 @@
 using namespace std;
 
 typedef vector<int> VI;
-typedef pair<int, int> PII;
-typedef vector<PII> VPII;
+#define MAX_N 1000
 
-#define STRICTLY_INCREASNG
 #include "LongestIncreasingSubsequence.cpp"
 
-int main() {
+void test1() {
   VI v = {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() == 10);
-  return 0;
+  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);
+  for(int i = 0; i < r.size()-1; i++)
+    assert(r[i] <= r[i+1]);
+  assert(r.size() == 12);
 }
+
+int main() {
+  test1();
+  test2();
+  return 0;
+}

+ 0 - 4
code/Makefile

@@ -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
 	@echo Compiling $@...
 	@$(CC) -o $@ $<