LIS,最长递增子序列
说明见:http://blog.csdn.net/sdjzping/article/details/8759870
1 #include <iostream> 2 #include <cstdlib> 3 4 using namespace std; 5 6 int LIS(int* arr, int len) { 7 if (arr == NULL || len < 1) return 0; 8 int LIS[len] = {0}; 9 int mlen = 0; 10 for (int i=0; i<len; i++) { 11 LIS[i] = 1; 12 for (int j = 0; j < i; j++) { 13 if (arr[j] < arr[i] && LIS[i] < LIS[j] + 1) { 14 LIS[i] = LIS[j] + 1; 15 } 16 } 17 if (LIS[i] > mlen) { 18 mlen = LIS[i]; 19 } 20 } 21 return mlen; 22 } 23 24 25 int main() { 26 int arr[] = {1, -1, 2, -3, 4, -5, 6, -7}; 27 int len = sizeof(arr) / sizeof(arr[0]); 28 cout<<LIS(arr, len)<<endl; 29 system("pause"); 30 return 0; 31 }
再给出nlogn的解法,其中len2val数组就是记录当前LIS长度时结尾的数字(可能情况下的最小值,如1,3和1,2同样可以构成长度为2的LIS但是取len2val[2]=2),关于这个数组的详细说明,可以参考第一个给出的连接,相对于第一个算法的改进就是该数组是有序的,可以使用二分搜索,即在数组中找到第一个比待处理值V大或相等的index设为I(就是序列长度),那么这个V必然可以插入到以len2val[I-1]结尾的长度为I-1的序列后部,形成新序列的长度为I,因而更新数组len2val[I] = V(更新是因为当前值肯定是大于等于V的,因为一开始就是根据这个条件进行搜索的)。这个查找的过程可以用STL中的lower_bound来做,这里自己按照源码写了一个直接返回索引的版本,STL中返回的是迭代器(数组迭代器就是元素指针,比较时还需减掉数组起始位置,才能得到索引)。
1 int idx_lower_bound(int a[], int begin, int end, int target) { 2 int count = end - begin; 3 int first = begin; 4 while (count > 0) { 5 int step = count/2; 6 int idx = first + step; 7 if (a[idx] < target) { 8 first = ++idx; 9 count = count - step - 1; 10 } else { 11 count = step; 12 } 13 } 14 15 return first; 16 } 17 18 int LIS_NLOGN(int arr[], int len) { 19 if (arr == NULL || len < 1) { 20 return 0; 21 } 22 int* len2idx = new int[len+1]; 23 24 len2idx[1] = arr[0]; 25 int maxlen = 1; 26 for (int i=1; i<len; i++) { 27 char ch = arr[i]; 28 int upper = idx_lower_bound(len2idx, 0, maxlen + 1, ch); 29 len2idx[upper] = ch; 30 if (upper > maxlen) { 31 maxlen = upper; 32 } 33 } 34 return maxlen; 35 }
LCS,最长公共子序列
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 5 using namespace std; 6 7 int max(int a, int b) { 8 return a > b ? a : b; 9 } 10 11 int LCS(const char* s1, int len1, const char* s2, int len2) { 12 if (s1 == NULL || s2 == NULL || len1 < 1 || len2 < 1) return 0; 13 14 int dp[len1 + 1][len2 + 1]; 15 16 for (int i=0; i<=len1; i++) { 17 for (int j=0; j<=len2; j++) { 18 dp[i][j] = 0; 19 } 20 } 21 22 for (int i=1; i<= len1; i++) { 23 for (int j=1; j<=len2; j++) { 24 if (s1[i-1] == s2[j-1]) { 25 dp[i][j] = dp[i-1][j-1] + 1; 26 } else { 27 dp[i][j] = max(dp[i-1][j], dp[i][j-1]); 28 } 29 } 30 } 31 for (int i=0; i<=len1; i++) { 32 for (int j=0; j<=len2; j++) { 33 cout<<" "<<dp[i][j]; 34 } 35 cout<<endl; 36 } 37 return dp[len1][len2]; 38 }; 39 40 int main() { 41 const char* s1 = "helloyyc"; 42 const char* s2 = "xellxddc"; 43 44 cout<<LCS(s1, strlen(s1), s2, strlen(s2))<<endl; 45 46 system("pause"); 47 return 0; 48 }