Longest common subsequence LCS
Lintcode 77. longest common subsequence
LCS problem is the sum of two strings of the longest common subsequence
\ [dp [i] [j ] = \ left \ {\ begin {matrix} & max (dp [i-1] [j], dp [i] [j-1]), s [i]! = s [j] \\ & dp [i-1] [j-1] + 1, s [i] == s [ j] \ end {matrix} \
right. \] many problems can be modified to solve the problem as LCS
class Solution {
public:
/**
* @param A: A string
* @param B: A string
* @return: The length of longest common subsequence of A and B
*/
int longestCommonSubsequence(string &A, string &B) {
// write your code here
int n = A.size();
int m = B.size();
std::vector<vector<int>> dp(m+1, vector<int>(n+1, 0)) ;
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
if(A[i-1] == B[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[m][n];
}
};
Because dp [i] [j] only uses the data i-1 and i-layer, can be used to scroll the array to the compression space, so that the degree of complexity of the space \ (O (min (m, n)) \)
class Solution {
public:
/**
* @param A: A string
* @param B: A string
* @return: The length of longest common subsequence of A and B
*/
int longestCommonSubsequence(string &A, string &B) {
// write your code here
int n = A.size();
int m = B.size();
std::vector<vector<int>> dp(2, vector<int>(n+1, 0)) ;
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
if(A[i-1] == B[j-1]) dp[i%2][j] = dp[(i-1)%2][j-1] + 1;
else dp[i%2][j] = max(dp[(i-1)%2][j], dp[i%2][j-1]);
}
}
return dp[m%2][n];
}
};
LIS longest increasing subsequence
300. Longest Increasing Subsequence
Dynamic Programming
Can be assumed dp [i] is to nums [i] at the end of the LIS length, dp [i] = max (dp [j] + 1) (j <i and nums [j] <nums [i ]), the time complexity degree \ (O (^ n-2) \) , the time complexity is \ (O (n) \)
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n, 1);
int MAX = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < i; j++){
if(nums[i] > nums[j]) dp[i] = max(dp[j] + 1, dp[i]);
}
MAX = max(MAX, dp[i]);
}
return MAX;
}
};
Greedy + half
First we set an auxiliary array v, where v [I] indicates the length of the LIS end value i-1, first scanning the original array, when the process to nums [i] and data v in the comparison, binary search final ratio nums [i] small value, and replace, if not, then added to the end, the final length is the length of the original array v LIS, the time complexity \ (nlgn \)
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
vector<int> v;
for(int i = 0; i < n; ++i){
auto loc = lower_bound(v.begin(), v.end(), nums[i]);
if(loc == v.end()) v.push_back(nums[i]);
else *loc = nums[i];
}
return v.size();
}
};
If only the required length and allow the LIS to change the original array, spatial complexity may be reduced to \ (O (1) \)
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
auto p = nums.begin();
auto q = nums.begin();
for(int i = 0; i < n; i++){
auto r = lower_bound(p, q, nums[i]);
if(r == q){ ++q; }
*r = nums[i];
}
return q - p;
}
};
LIS and the LCS interconversion
LIS LCS problem can be transformed into the problem, such as the input array [5,1,4,2,3], longest increasing sequence is [2,3], may first obtain a new original array sorted array [1 , 2,3,4,5], then the original array with the new array as inputs to solve the LCS, the time complexity is \ (O (n ^ 2) \ ) , the spatial complexity degree \ (O (n ^ 2) \ )
LIS LCS problem can become problems, assuming that the input array is an array of numbers such as A = [1,7,5,4,8,3,9], B = [1,4,3,5,6,2,8 , 9], and the two sequences a, B each element varies (e.g., 1-n is arranged), if the LCS solving the longest common subsequence length, complexity \ (O (n ^ 2 ) \) , A, B each element in the two sequences is different, so we can re-encode A A = [1,2,3,4,5,6,7] (coding not repeated), B can be encoded as B = [1,4,6,3,0,0,5,7] (0 indicates absence, may be directly deleted), and then re-encoded after the request a, LIS length B, the time complexity is \ (O (nlgn) \)
LCS longest palindromic sequence variants and LPS
Longest palindromic sequence may be used to request LCS S idea obtained by inverting the first S S ', then find LCS (S, S')
leetcode 516. Longest palindromic Subsequence
class Solution {
public:
int lcs(string &A, string &B) {
int n = A.size();
int m = B.size();
std::vector<vector<int>> dp(m+1, vector<int>(n+1, 0)) ;
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
if(A[i-1] == B[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[m][n];
}
int longestPalindromeSubseq(string s) {
string t(s.rbegin(), s.rend());
return lcs(s, t);
}
};
Variants: S anywhere in seeking to insert or delete such that S is a minimum number of characters palindromic sequence
Solution: first find the longest palindromic sequence, then the length of the original length -LPS
Not for the length of the original sequence seek
reference
- LIS algorithm: the longest rising sequence
- Introduction to the classic race algorithm - example 27: Prince and Princess
- Introduction to Algorithms, Third Edition Questions 15-2