LIS 最長遞增子串行

2021-07-15 12:34:54 字數 1640 閱讀 7984

在電腦科學中,最長遞增子串行(longest increasing subsequence)問題是指,在乙個給定的數值串行中,找到乙個子串行,使得這個子串行元素的數值依次遞增,並且這個子串行的長度盡可能地大。最長遞增子串行中的元素在原序列中不一定是連續的

– 維基百科

1 3 4 2 5則最長遞增子串行為1 3 41 3 51 4 5,長度都為3。

設dp[i]為arr[i]為結尾的lis長度,則顯然

dp[i] = max , j < i && arr[j] < arr[i]
注意下初始情況下dp[i]為1,然後**就easy了

const int maxn = 1000;

const int inf = 0x7f;

int lis_dp(int *arr, int n)

}if (dp[i] > ans)

ans = dp[i];

}return ans;

}

我們發現上面的第二層迴圈只是找個max(dp[j]),那麼就可以用二分優化,但不是直接的把第二個迴圈換成二分查詢,直接看**。

定義陣列

f[i]:以arr[i]結尾的lis長度

g[i]:長度為i的lis的最後個數字,長度相同時取最小的結尾數字

其中的g[i]在相同長度時,比如1 3 4 2 5的lis為1 3 41 3 51 4 5,則g[3]為4,因為顯然長度相等情況下最後個數字更小更好。

int lis(int *arr, int n) 

return ans;

}

關鍵在於lower_bound的引數+1和返回值,我們遍歷每個數字的時候在g裡取》=arr[i]的第乙個位置,這個位置(從1開始計數的話)就是以arr[i]結尾的lis的長度(即f[i]),且當前這個數字也是這個長度下的g值(即g[f[i]])。

上個例子看看

n = 5

arr: 10 30 15 20 60

f: 1 2 2 3 4

g[f]: 10 30 15 20 60

帶著f和g的定義去想**流程就容易想通的,這裡不具體分析了,下面給一些關鍵點

我們可以將原陣列複製乙份,然後對新陣列排序,之後求原陣列和新陣列的lcs(最長公共子串行)即是答案,複雜度o(nn),也需要開個nn的空間,比較傷。

int lis_lcs(int *arr, int n)  else }}

return dp[n][n];

}

poj 2533 裸lis 兩種解法都能過

hdu 5748 bellovin - bc 84期b題

給乙個序列a,要求找出另外個序列b,符合每個以b[i]結尾的lis都和a[i]的一樣且序列b是所有解中字典序最小的。

你會發現 序列a的lis陣列本身就是答案,它的長度代表了字典序最小。

最長遞增子串行 LIS

對於這個問題,最直觀的dp方法是cnt i 表示以height i 結束的最長遞增子串行的元素的個數,遞迴方程是cnt i max for max i 0 i求出整個數列的最長遞增子串行的長度 if b i max max b i cout return 0 顯然,這種方法的時間複雜度仍為o n 2...

最長遞增子串行 LIS

給定乙個長度為n的陣列,找出乙個最長的單調自增子序列 不一定連續,但是順序不能亂 例如 給定乙個長度為6的陣列a,則其最長的單調遞增子串行為,長度為4.這個問題可以轉換為最長公共子串行問題。如例子中的陣列a,則我們排序該陣列得到陣列a 然後找出陣列a和a 的最長公共子串行即可。顯然這裡最長公共子串行...

最長遞增子串行(LIS)

300.longest increasing subsequence good 給定乙個長度為n的陣列,找出乙個最長的單調遞增子串行 不一定連續,當時先後順序不能亂 更正式的定義是 設l 是n個不同的實數的序列,l的遞增子串行是這樣乙個子串行lin 其中k1。比如陣列a 為,那麼最長遞增子串行為。以...