动态规划-最长公共自序列(java)

package com.wanali.dynamic_planning;
/**
 * 最长公共自序列LCS(动态规划求解)
 * @author wan_ys
 *
 * 2019年1月10日上午8:43:34
 */
public class LCS {
	public static void main(String[] args) {
		String[] x = new String[] { "A", "B", "C", "B", "D", "A", "B" };
		String[] y = new String[] { "B", "D", "C", "A", "B", "A" };
		getLCSLength(x, y);

	}
	/**
	 * 计算LCS的长度
	 * @param x 
	 * @param y
	 */
	static void getLCSLength(String[] x, String[] y) {
		int m = x.length + 1;
		int n = y.length + 1;
		int[][] b = new int[m][n];//定义LCS长度数组
		String[][] c = new String[m][n]; //记录回溯方向,方便找公共子序列
		//初始化第一列为0
		for (int i = 0; i < m; i++) {
			b[i][0] = 0;
		}
		//初始化第一行为0
		for (int j = 0; j < n; j++) {
			b[0][j] = 0;
		}
		/*从(1,1)开始往后比较x[i]==y[j],b[i][j]=c[i-1][j-1]+1;
		 * b[i-1][j]>=b[i][j-1],则该位置的箭头向上指
		 * b[i][j-1]>b[i-1][j],则该位置的箭头向左指
		*/
		for (int i = 1; i < m; i++) {
			for (int j = 1; j < n; j++) {
				//注意这里应该是x[i-1]和y[j-1]
				if (x[i - 1] == y[j - 1]) {
					b[i][j] = b[i - 1][j - 1] + 1;
					c[i][j] = "upleft";
				} else if (b[i - 1][j] >= b[i][j - 1]) {//上边位置大于等于左边位置
					b[i][j] = b[i - 1][j];
					c[i][j] = "up";
				} else {//左边位置大于上边位置
					b[i][j] = b[i][j - 1];
					c[i][j] = "left";
				}
			}

		}
		//打印公共子序列的长度
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				System.out.print(b[i][j] + "\t");
			}
			System.out.println();
		}
		//打印回溯方向
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				System.out.print(c[i][j] + "\t");
			}
			System.out.println();
		}
		System.out.println("一个最长公共自序列为:");
		//注意这里是m-1,n-1
		getLCS(c, x, m-1, n-1);
	}

	static void getLCS(String[][] c, String[] x, int i, int j) {
		if (i == 0 || j == 0) {
			return;
		} 
		if (c[i][j] == "upleft") {
			getLCS(c, x, i - 1, j - 1);
			System.out.print(x[i - 1]);
		} else if (c[i][j] == "up") {
			getLCS(c, x, i - 1, j);
		} else {
			getLCS(c, x, i, j - 1);
		}
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值