[algorithm sorting] LCS, LIS, LCIS, K_LCS,K_LIS,K_LCIS

Posted by phoolster on Fri, 18 Feb 2022 20:52:27 +0100

*** Code analysis has not been done yet. It needs to be supplemented if necessary. Please specify the contents that need to be supplemented in the comment area.

 

LCS | longest common subsequence

Problem descriptionGiven two strings A and B with lengths of N and M respectively, find the longest string length of both A subsequence and B subsequence.
Problem solving ideasNo, it needs to be supplemented
matters needing attentionNo, it needs to be supplemented
Example websiteNo, it needs to be supplemented
  • Regular Edition
public static int LCS(int[] arrn, int[] arrm) {
	int[][] dp = new int[arrn.length+1][arrm.length+1];
	for(int i=1; i<=arrn.length; ++i) {
		for(int j=1; j<=arrm.length; ++j) {
			if(arrn[i-1] == arrm[j-1]) 
				dp[i][j] = dp[i-1][j-1]+1;
			else
				dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
		}
	}
	return dp[arrn.length][arrm.length];
}
	
  • Optimized version
public static int LCS(int[] arrn, int[] arrm) {
	int[][] dp = new int[2][arrm.length+1];
	for(int i=1; i<=arrn.length; ++i) {
		int cur = i%2, prev = (i-1)%2;
		for(int j=1; j<=arrm.length; ++j) {
			if(arrn[i-1] == arrm[j-1]) 
				dp[cur][j] = dp[prev][j-1]+1;
			else
				dp[cur][j] = Math.max(dp[prev][j], dp[cur][j-1]);
		}
	}
	return dp[arrn.length%2][arrm.length];
}
	

 

LIS | longest ascending subsequence

Problem descriptionGiven A string A of length N, find the longest length of the monotonically increasing subsequence.
Problem solving ideasNo, it needs to be supplemented
matters needing attentionNo, it needs to be supplemented
Example websiteNo, it needs to be supplemented
  • Regular Edition
public static int LIS(int[] arr) {
	int[] dp = new int[arr.length];
	Arrays.fill(dp, 1);
	int ans = dp[0];
	for(int i=1; i<arr.length; ++i) {
		for(int j=0; j<i; ++j) {
			if(arr[i] > arr[j]) 
				dp[i] = Math.max(dp[i], dp[j]+1);
		}
		ans = Math.max(ans, dp[i]);
	}
	return ans;
}

 

LCIS | longest common ascending subsequence

Problem descriptionGiven two strings A and B with lengths of N and M respectively, find the maximum length of the string that is both A subsequence and B subsequence and monotonically increasing in value.
Problem solving ideasNo, it needs to be supplemented
matters needing attentionNo, it needs to be supplemented
Example websiteNo, it needs to be supplemented
  • Regular Edition
public static int LCIS(int[] arrn, int[] arrm) {
	int[][] dp = new int[arrn.length + 1][arrm.length + 1];
	int ans = 0;
	for (int i = 1; i <= arrn.length; ++i) {
		int val = 0;
		for (int j = 1; j <= arrm.length; ++j) {
			if (arrn[i - 1] == arrm[j - 1]) {
				dp[i][j] = val + 1;
				ans = Math.max(ans, dp[i][j]);
			} else {
				dp[i][j] = dp[i - 1][j];
				if (arrn[i - 1] > arrm[j - 1])
					val = Math.max(val, dp[i - 1][j]);
			}
		}
	}
	return ans;
}

  • Optimized version
public static int LCIS(int[] arrn, int[] arrm) {
	int[][] dp = new int[2][arrm.length + 1];
	int ans = 0;
	for (int i = 1; i <= arrn.length; ++i) {
		int val = 0, cur = i % 2, prev = (i - 1) % 2;
		for (int j = 1; j <= arrm.length; ++j) {
			if (arrn[i - 1] == arrm[j - 1]) {
				dp[cur][j] = val + 1;
				ans = Math.max(ans, dp[cur][j]);
			} else {
				dp[cur][j] = dp[prev][j];
				if (arrn[i - 1] > arrm[j - 1])
					val = Math.max(val, dp[prev][j]);
			}
		}
	}
	return ans;
}

 

K_LCS | common subsequence with length k

Problem descriptionGiven two strings A and B with length N and M respectively, find the number of strings with length K that are both subsequences of A and B.
Problem solving ideasNo, it needs to be supplemented
matters needing attentionNo, it needs to be supplemented
Example websiteNo, it needs to be supplemented
  • Regular Edition
public static int K_LCS(int[] arrn, int[] arrm, int k) {
	int dp[][][] = new int[arrn.length + 1][arrm.length + 1][k + 1];
	int ans = 0;
	for (int i = 1; i <= arrn.length; ++i) {
		for (int j = 1; j <= arrm.length; ++j) {
			for (int h = 1; h <= k; ++h)
				dp[i][j][h] = dp[i - 1][j][h] + dp[i][j - 1][h] - dp[i - 1][j - 1][h];
			if (arrn[i - 1] == arrm[j - 1]) {
				++dp[i][j][1];
				for (int h = 2; h <= k; ++h)
					dp[i][j][h] += dp[i - 1][j - 1][h - 1];
			}
		}
	}
	return dp[arrn.length][arrm.length][k];
}

  • Optimized version
public static int K_LCS(int[] arrn, int[] arrm, int k) {
	int dp[][][] = new int[2][arrm.length + 1][k + 1];
	int ans = 0;
	for (int i = 1; i <= arrn.length; ++i) {
		int cur = i % 2, prev = (i - 1) % 2;
		for (int j = 1; j <= arrm.length; ++j) {
			for (int h = 1; h <= k; ++h)
				dp[cur][j][h] = dp[prev][j][h] + dp[cur][j - 1][h] - dp[prev][j - 1][h];
			if (arrn[i - 1] == arrm[j - 1]) {
				++dp[cur][j][1];
				for (int h = 2; h <= k; ++h)
					dp[cur][j][h] += dp[prev][j - 1][h - 1];
			}
		}
	}
	return dp[arrn.length % 2][arrm.length][k];
}
	

 

K_LIS | ascending subsequence with length k

Problem descriptionGiven A string A of length N, find the number of subsequences with monotonically increasing values and length K.
Problem solving ideasNo, it needs to be supplemented
matters needing attentionNo, it needs to be supplemented
Example websiteNo, it needs to be supplemented
  • Regular Edition
public static int K_LIS(int[] arr, int k) {
	int[][] dp = new int[arr.length][k + 1];
	int ans = 0;
	for (int i = 0; i < arr.length; ++i)
		dp[i][1] = 1;
	for (int i = 1; i < arr.length; ++i) {
		for (int j = 0; j < i; ++j) {
			if (arr[i] > arr[j])
				for (int h = 2; h <= k; ++h)
					dp[i][h] += dp[j][h - 1];
		}
		ans += dp[i][k];
	}
	return ans;
}

 

K_LCIS | common ascending subsequence with length k

Problem descriptionGiven two strings A and B with length N and M respectively, find the number of strings that are both subsequence of A and subsequence of B with monotonically increasing value and length K.
Problem solving ideasNo, it needs to be supplemented
matters needing attentionNo, it needs to be supplemented
Example websiteNo, it needs to be supplemented
  • Regular Edition
public static int K_LCIS(int[] arrn, int[] arrm, int k) {
	int[][][] dp = new int[arrn.length + 1][arrm.length + 1][k + 1];
	int ans = 0;
	for (int i = 1; i <= arrn.length; ++i) {
		int[] val = new int[k + 1];
		for (int j = 1; j <= arrm.length; ++j) {
			if (arrn[i - 1] == arrm[j - 1]) {
				dp[i][j][1] = 1;
				for (int h = 2; h <= k; ++h)
					dp[i][j][h] = val[h - 1];
				ans += dp[i][j][k];
			} else {
				for (int h = 0; h <= k; ++h)
					dp[i][j][h] = dp[i - 1][j][h];
				if (arrn[i - 1] > arrm[j - 1]) {
					for (int h = 0; h <= k; ++h)
						val[h] += dp[i - 1][j][h];
				}
			}
		}
	}
	return ans;
}

  • Optimized version
public static int K_LCIS(int[] arrn, int[] arrm, int k) {
	int[][][] dp = new int[2][arrm.length + 1][k + 1];//The following code optimizes the space
	int ans = 0;
	for (int i = 1; i <= arrn.length; ++i) {
		int[] val = new int[k + 1];
		int cur = i % 2, prev = (i - 1) % 2; // It's OK to write (i-1)%2 here
		for (int j = 1; j <= arrm.length; ++j) {
			if (arrn[i - 1] == arrm[j - 1]) {
				dp[cur][j][1] = 1;
				for (int h = 2; h <= k; ++h)
					dp[cur][j][h] = val[h - 1];
				ans += dp[cur][j][k];
			} else {
				dp[cur][j] = dp[prev][j].clone();
				if (arrn[i - 1] > arrm[j - 1]) {
					for (int h = 0; h <= k; ++h)
						val[h] += dp[prev][j][h];
				}
			}
		}
	}
	return ans;
}