lis的实现有三种,一种是简单的O(n^2)的dp,第二种是转化为lcs,用原序列排序后得到一个有序的序列,并求两序列的最长公共子序列。这种可以比较方便地打印出答案,复杂度也是O(n^2)。最后是维护一个为某个长度时该长度序列的最后一个数可取的最小值,用了二分查找将复杂度降到O(nlogn)。
1 //LIS 2 #include <iostream> 3 #include <algorithm> 4 #include <list> 5 #include <vector> 6 7 using namespace std; 8 9 int dp[105]; 10 11 void lis(int *p, int n) { 12 memset(dp, 0, sizeof(dp)); 13 14 for (int i = 1;i < n;i++) { 15 dp[i] = dp[i - 1]; 16 for (int j = 0;j < i;j++) 17 if (p[i] > p[j])dp[i] = max(dp[i], dp[j] + 1); 18 } 19 cout << dp[n - 1]; 20 } 21 22 int d[105][105]; 23 void lcs(int*p, int* q, int m, int n) {//m,n为两个数组的长度 24 25 memset(d, 0, sizeof(d)); 26 27 for (int i = 1;i<m + 1;i++) 28 for (int j = 1;j < n + 1;j++) { 29 if (p[i - 1] == q[j - 1])d[i][j] = d[i - 1][j - 1] + 1; 30 else d[i][j] = max(d[i - 1][j], d[i][j - 1]); 31 } 32 } 33 34 void print_ans(int* p, int* q, int m, int n) {//lcs的打印 35 if (d[m][n] <= 0)return; 36 37 if (d[m][n] == d[m - 1][n - 1] + 1) { 38 print_ans(p, q, m - 1, n - 1); 39 cout << p[m - 1]; 40 } 41 else if (d[m][n] = d[m - 1][n]) 42 print_ans(p, q, m - 1, n); 43 else 44 print_ans(p, q, m, n - 1); 45 //cout << endl; 46 } 47 48 int binarysearch(int* a, int len, int val) { 49 int left = 0, right = len;//左闭右开 50 while (left < right) { 51 int mid = (left + right) / 2; 52 if (a[mid] > val) 53 right = mid; 54 else if (a[mid] < val) 55 left = mid + 1; 56 else 57 return mid; 58 } 59 return left; 60 } 61 62 int lis1(int *p, int n) { 63 int *a = new int[n]; 64 int length = 1; 65 a[0] = p[0]; 66 67 for (int i = 1;i < n;i++) { 68 if (p[i] > a[length - 1]) 69 a[length++] = p[i]; 70 else 71 a[binarysearch(a, length, p[i])] = p[i]; 72 } 73 74 delete a; 75 return length; 76 }