古典的な問題を振り返るアルゴリズム:LIS,LCS-(DPカテゴリ)

16977 ワード

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の解法は、len 2 val配列が現在のLIS長を記録するときの終端の数字である(可能性がある場合の最小値、例えば、1,3と1,2のように長さ2のLISを構成することができるが、len 2 val[2]=2)。この配列の詳細な説明については、最初に与えられた接続を参照することができ、最初のアルゴリズムの改善は、配列が秩序化されている。二分割検索を使用することができます。すなわち、処理対象値Vよりも大きいか等しい最初のindexをIに設定すると、このVは、必ずlen 2 val[I-1]で終わる長さI-1のシーケンスの後に挿入できます。新しいシーケンスを形成する長さはIであり、したがって、より新しい配列len 2 val[I]=V(更新は、現在の値がVに相当するためです。最初はこの条件に基づいて検索しています。)この検索の過程はSTLのlowerbandで行うことができます。ここで自分はソースに従ってインデックスのバージョンを書いています。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 }