Java_动态规划|回溯|最长公共子序列(Longest Common Sequence)|LCS

/**
 * 核心算法: 
 * 当i=0||j=0时,c[i,j]=0 
 * 当xi=yj时,c[i,j]=c[i-1,j-1]+1 
 * 当xi!=yj时,c[i,j]=max{c[i-1,j],c[i,j-1]}
 * 
 * @author Chill Lyn
 *
 */
class LongestCommonSequence {
	public static void main(String[] args) {
		// 定义两个字符串
		String x = "0358646";
		String y = "142386";

		lcs(x, y);
	}

	public static void lcs(String x, String y) {
		// 定义动态规划二维数组
		int[][] c = new int[x.length() + 1][y.length() + 1];

		for (int j = 0; j < y.length() + 1; j++) {
			for (int i = 0; i < x.length() + 1; i++) {
				// 当i=0||j=0时 c[i,j]=0
				// 定义动态数组时,数组内元素默认值为0
				// 此处if语句方便理解算法
				if ((i == 0) || (j == 0)) {
					c[i][j] = 0;
					// 当xi=yj时 c[i,j]=c[i-1,j-1]+1
				} else if (x.charAt(i - 1) == y.charAt(j - 1)) {
					c[i][j] = c[i - 1][j - 1] + 1;
					// 当xi!=yj时 c[i,j]=max{c[i-1,j],c[i,j-1]}
				} else {
					c[i][j] = Math.max(c[i][j - 1], c[i - 1][j]);
				}

			}
		}

		// 打印动态规划表c[i,j]
		System.out.println("动态规划表c[i,j]:");
		for (int j = 0; j < y.length() + 1; j++) {
			for (int i = 0; i < x.length() + 1; i++) {
				System.out.print(c[i][j] + "\t");
			}
			System.out.println();
		}

		// 回溯 公共子序列
		int i = x.length();
		int j = y.length();

		StringBuilder sb = new StringBuilder();
		while (i > 0 && j > 0) {
			// 当xi=yj时 c[i,j]=c[i-1,j-1]+1
			if (x.charAt(i - 1) == y.charAt(j - 1)) {
				sb.append(x.charAt(i - 1));
				i--;
				j--;
				// 上>左,向上推
			} else if (c[i][j - 1] > c[i - 1][j]) {
				j--;
				// 上<左,向左推
			} else if (c[i][j - 1] < c[i - 1][j]) {
				i--;
				// 上=左,两个方向皆可
			} else if (c[i][j - 1] == c[i - 1][j]) {
				i--;
				// 这种情况有两条分支,或者可选择j--;
			}
		}
		System.out.println("Longest Common Sequence:");
		System.out.println(sb.reverse().toString());
	}
}

结果
Java_动态规划|回溯|最长公共子序列(Longest Common Sequence)|LCS_第1张图片
回溯LCS图解
Java_动态规划|回溯|最长公共子序列(Longest Common Sequence)|LCS_第2张图片

你可能感兴趣的:(Java_基础,算法入入门(杂))