算法基础之动态规划

Posted by Naah on Saturday, Sep 09,2017 11:43:36

动态规划

把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划

算法应用

最长公共子序列问题

提供给你两个字符串,求出最长的公共字符串是多少位,不要求连续

/**
 * 动态规划
 * 最长公共子序列LCS
 * 2017年9月9日 下午4:39:53
 *
 */
public class LCS {
	public int findLCS(String A, String B) {

		// A串长度
		int n = A.length();

		// B串长度
		int m = B.length();

		// A串字符数组
		char[] a = A.toCharArray();

		// B串字符数组
		char[] b = B.toCharArray();

		// 二维数组
		// A为行
		// B为列
		int[][] dp = new int[n][m];

		// 遍历比对A串每一个字母与B串第一个字母
		// A串为行
		// 遍历行
		for (int i = 0; i < n; i++) {

			// A串每个字母与B串第一个字母进行比对
			if (a[i] == b[0]) {

				// 如果A串的字母与B串的第一个字母相等
				// 则这行第一列赋值为1
				dp[i][0] = 1;

				// 将这行下面所有行赋值为1
				// 表示从该位置开始至后面都有一个公共字符串
				// 比如下面这个串,android从r开始的字符串都与random有一个公共子序列r
				// android
				///// random
				for (int j = i + 1; j < n; j++) {
					dp[j][0] = 1;
				}

				// 跳出循环
				break;
			}
		}

		// 遍历比对B串的每一个字母与A串第一个字母
		// B串为列
		// 遍历列
		for (int i = 0; i < m; i++) {// 第一行

			// B串的每个字母与A串的第一个字母进行比对
			if (a[0] == b[i]) {

				// 如果B串的字母与A串的第一个字母相等
				// 则这列第一行赋值为1
				dp[0][i] = 1;

				// 将这行后面所有列赋值为1
				// 表示从该位置开始至后面都有一个公共字符串
				for (int j = i + 1; j < m; j++) {
					dp[0][j] = 1;
				}
				break;
			}
		}

		// 遍历二维数组,从1开始
		for (int i = 1; i < n; i++) {
			for (int j = 1; j < m; j++) {

				// 如果两个字母相等
				if (a[i] == b[j]) {
					// 则该位置等于前两个字母比对的位置+1
					// 表示公共子序列的长度+1
					dp[i][j] = dp[i - 1][j - 1] + 1;

					// 否则
				} else {

					// 该位置等于 该位置的上面一行位置 与 该位置的前面一列位置 最大的值
					// dp[i - 1][j]:该位置上面一行位置 表示:A串当前字符的上一个字符与B串当前字符的最长子序列长度
					// dp[i][j - 1]:该位置前面一列位置 表示:A串当前字符与B串当前字符的上依噶字符的最长子序列长度
					dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
				}
			}
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				System.out.print(dp[i][j] + " ");
			}
			System.out.println();
		}

		// 二维数组最右下角的元素表示最长子序列长度
		return dp[n - 1][m - 1];
	}

	public static void main(String[] args) {
		LCS lcs = new LCS();
		int findLCS = lcs.findLCS("android", "random");
		System.out.println("最长子序列长度:" + findLCS);
	}
}