7-10 最长公共子序列长度 java 题解

题目描述:

 

求两个字符串的最长公共子序列长度。

输入格式:

输入长度≤100的两个字符串。

输出格式:

输出两个字符串的最长公共子序列长度。

输入样例1:

ABCBDAB
BDCABA

输出样例1:

4

输入样例2:

ABACDEF
PGHIK

输出样例2:

0

解题思路:

子序列区别于子串,前者可以不连续但不能乱了顺序,后者为连续的字符串。

求两串的最长公共子序列长度,可以分别将两字符串想象为二维数组的行和列,先将左上边界置为0,当某一位置dp[i][j]相等时,将dp[i - 1][j - 1] + 1,若不相等,则选左或上的最大值。最后输出右下角的值即为最长长度。

例如第五行 和第七列的A,此时相等,前面匹配了两个字母,为"BC",不能讲A匹配进去,所以是将左上对角线上的值加上此时匹配的A,共3个字符。反之,若不相等时,直接选一个最大值即可。


7-10 最长公共子序列长度 java 题解_第1张图片

 若要求最长子序列的值,则需要倒着从右下角往回遍历,当且仅当两字符串相等时,让i--,j--,同时将此时的字符拼接到String上。 若不相等,则比较是上值大还是左值大,上值大则i--,否则j--,最后将String再反转便可得到所求最大子序列值。

java代码:(求最长序列)

public static void getMaxString(int [][]dp,String s1,String s2) {
	boolean flag = true;
	StringBuilder builder = new StringBuilder();
	for(int i = dp.length - 1; ;) {//数组长度-1为数组索引最大值
		if(i == 0)//已到上边界,退出循环
			break;
		for(int j = dp[i].length - 1; ;) {
			if(j == 0) {
				flag = false;
				break;//已到左边界,退出循环
			}
			if(s1.charAt(i - 1) == s2.charAt(j - 1)) {//开始有辅助的最上行和最左行,需减去
				builder.append(s1.charAt(i - 1));//保存此时字符
				i--;//回退到左上角
				j--;
			}else {
				if(dp[i - 1][j] >= dp[i][j - 1]) {
					i--;//回退到上一行
				}else {
					j--;//回退到前一列
				}
			}
		}
		if(!flag)
			break;
	}
	System.out.println(builder.reverse().toString());
}

javaAC代码:(求最长长度)

import java.io.*;

public class Main {
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String s1 = br.readLine();
		String s2 = br.readLine();
		int len1 = s1.length();
		int len2 = s2.length();
		int [][]arr = new int[len1 + 1][len2 + 1];
		for(int i = 1; i < arr.length;i++) {
			for(int j = 1; j < arr[i].length;j++) {
				int max = Math.max(arr[i][j - 1], arr[i - 1][j]);
				if(s1.charAt(i -1) == s2.charAt(j - 1)) {
					arr[i][j] = arr[i - 1][j - 1] + 1;
				}else {
					arr[i][j] = max;
				}
			}
		}
		System.out.println(arr[len1][len2]);
	}
}

你可能感兴趣的:(动态规划,java,算法,动态规划,最长子序列)