最長單調遞增子序列php
解題思想:動態規劃ios
1.解法1(n2)數組
狀態:d[i] = 長度爲i+1的遞增子序列的長度ide
狀態轉移方程:dp[i] = max(dp[j]+1, dp[i]);優化
分析:最開始把dp數組初始化爲1,而後從前日後考慮數列的元素,對於每一個aj,若是a[i] > a[j],就用dp[i] = max(dp[i], dp[j] + 1)進行更新,再從dp數組中找出最大值即爲結果spa
舉例:abklmncdefg指針
dp[0] = 1; dp[1] = 2; dp[2] = 3; dp[3] = 4; dp[4] = 5; dp[5] = 6; dp[7] = 3; dp[8] = 4; dp[9] = 5; dp[10] = 6; dp[11] = 7; 最大值爲7code
代碼:blog
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int MAX_N = 10005; 6 int n; 7 char a[MAX_N]; 8 int dp[MAX_N]; 9 int main() { 10 int n; 11 cin >> n; 12 while(n--) { 13 int ans = 0; 14 fill(dp, dp+MAX_N, 1); 15 cin >> a; 16 int len = strlen(a); 17 for(int i = 0; i < len; i++) { 18 for(int j = 0; j < i; j++) { 19 if(a[j] < a[i]) dp[i] = max(dp[i], dp[j] + 1); 20 } 21 ans = max(ans, dp[i]); 22 } 23 cout << ans << endl; 24 } 25 return 0; 26 }
2.解法2(n2)ci
狀態:d[i] = 長度爲i+1的遞增子序列中末尾的最小值(不存在就是INF)
分析:最開始用INF初始化dp數組的值,而後從前日後考慮數列的元素,對於每一個aj,若是i = 0或者a[j] >= a[i],使得a[j] = a[i]而且break出來,最後第一個dp數組中值爲INF的下標即爲結果
舉例:abklmncdefg
a; ab; abk; abkl; abklm; abklmn; abclmn; abcdmn; abcden; abcdef; abcdefg; 第一個INF的下標爲7
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int MAX_N = 10005; 6 const int INF = 127; 7 int n; 8 char a[MAX_N]; 9 char dp[MAX_N]; 10 int main() { 11 int n; 12 cin >> n; 13 while(n--) { 14 fill(dp, dp+MAX_N, INF); 15 cin >> a; 16 int len = strlen(a); 17 for(int i = 0; i < len; i++) { 18 for(int j = 0; j < len; j++) { 19 if(!i || dp[j] >= a[i]) { 20 dp[j] = a[i]; break; 21 } 22 } 23 } 24 int ans = 0; 25 while(dp[ans] != INF) ans++; 26 cout << ans << endl; 27 } 28 return 0; 29 }
3.解法3(nlogn)
分析:思路與解法2同樣,可是解法2能夠進一步優化,在解法2中dp數組是單調遞增的,每次要從頭至尾找到第一個大於等於a[i]的值,這是o(n2)的,既然是順序的能夠使用二分查找進行改進,
這樣能夠在o(nlogn)時間內求出結果,這裏利用到了STL中的lower_bound(dp, dp + n, a[i]),找出dp數組中大於等於a[i]的最小的指針,upper_boundlower_bound(dp, dp + n, a[i]),找出dp數組中大於a[i]的最大的指針
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int MAX_N = 10005; 7 const int INF = 127; 8 int n; 9 char a[MAX_N]; 10 char dp[MAX_N]; 11 int main() { 12 int n; 13 cin >> n; 14 while(n--) { 15 fill(dp, dp+MAX_N, INF); 16 cin >> a; 17 int len = strlen(a); 18 for(int i = 0; i < len; i++) { 19 *lower_bound(dp, dp+len, a[i]) = a[i]; 20 } 21 cout << lower_bound(dp, dp+len, INF) - dp << endl; 22 } 23 return 0; 24 }