1. 程式人生 > >【筆記】最長遞增子序列 Longest increasing subsequence(LIS)

【筆記】最長遞增子序列 Longest increasing subsequence(LIS)

http range element -m 元素 筆記 pro 最長公共子序列 .org

介紹和解法,參見wikipedia https://en.wikipedia.org/wiki/Longest_increasing_subsequence

筆記:

在按下標順序遍歷序列 X 的過程中,記錄所有不同長度 L 的增長最慢的遞增子序列,因為序列是遞增的,只需要記錄其最大元素,記為 M[L]

比如,對於序列 5,8,9,6,7,在訪問 6 之前,M[1]=5,M[2]=8,M[3]=9。

訪問 6 時,長度為2 的增長最慢的遞增子序列為5,6,因此 M[2] 變為 6。

同理,訪問 7 時, M[3] 變為 7。

遍歷結束後,M 的長度即為 LIS 的長度,但並不知道這個 LIS 是什麽。

為了得到 LIS,將原來 M 保存的數據改為該數據在序列 X 中的 index;

並且,在遍歷 X 的過程中,記錄每個元素 X[i] 在候選的遞增子序列中的前驅元素在序列 X 中的 index,記為P[i]

這樣在遍歷結束後,就可以從後往前輸出 LIS:記 M 長度為 m,有:

LIS[m]   = X[    M[m]  ]
LIS[m-1] = X[  P[M[m]] ]
LIS[m-2] = X[P[P[M[m]]]]
......

wikipedia 原文引用如下:

It processes the sequence elements in order, maintaining the longest increasing subsequence found so far. Denote the sequence values as X[0], X[1], etc. Then, after processing X[i

], the algorithm will have stored values in two arrays:

M[j] — stores the index k of the smallest value X[k] such that there is an increasing subsequence of length j ending at X[k] on the range ki. Note that j(i+1), because j ≥ 1 represents the length of the increasing subsequence, and k ≥ 0 represents the index of its termination.
P[k] — stores the index of the predecessor of X[k] in the longest increasing subsequence ending at X[k].

 P = array of length N
 M = array of length N + 1

 L = 0
 for i in range 0 to N-1:
   // Binary search for the largest positive j ≤ L
   // such that X[M[j]] < X[i]
   lo = 1
   hi = L
   while lo ≤ hi:
     mid = ceil((lo+hi)/2)
     if X[M[mid]] < X[i]:
       lo = mid+1
     else:
       hi = mid-1

   // After searching, lo is 1 greater than the
   // length of the longest prefix of X[i]
   newL = lo

   // The predecessor of X[i] is the last index of 
   // the subsequence of length newL-1
   P[i] = M[newL-1]
   M[newL] = i

   if newL > L:
     // If we found a subsequence longer than any we‘ve
     // found yet, update L
     L = newL

 // Reconstruct the longest increasing subsequence
 S = array of length L
 k = M[L]
 for i in range L-1 to 0:
   S[i] = X[k]
   k = P[k]

 return S

相關問題:

最長先遞增再遞減子序列 牛客網 https://www.nowcoder.com/practice/6d9d69e3898f45169a441632b325c7b4?tpId=37&tqId=21247&tPage=1&rp=&ru=/ta/huawei&qru=/ta/huawei/question-ranking

看了解法,思路如下:

遍歷序列 X,得到以 X[i] 結尾的 LIS 的長度 Li[i] 和以 X[i] 開始的 LDS 的長度 Ld[i], 找到 Li[i] + Ld[i] 的最大值;

將 X 反向再求 LIS 即最長遞減子序列 LDS;

在上述解法中加入 Li[i]:Li[i] = L[P[i]] + (newL > L) ? 1 : 0

最長公共子序列 Longest Common Subsequence(LCS) 可參見算法導論

TODO: Longest Common Subsequence for Multiple Sequences https://stackoverflow.com/questions/5752208/longest-common-subsequence-for-multiple-sequences

【筆記】最長遞增子序列 Longest increasing subsequence(LIS)