动态规划之最长公共子序列

一个给定序列的子序列是在该序列中删去若干元素后得到的序列。若给定序列X={x1, x2, ..., xm},则另一序列Z={z1, z2, ..., zk},X的子序列是指存在一个严格递增下标序列i, 使得对于所用的j=1, 2, 3,...,k有zj = xi.

例如:序列X={A, B, C, B, D, A, B}的一个子序列Z={B, C, D, A}。

给定两个序列X和Y, 当另一序列Z既是X的子序列又是Y的子序列,则称Z为X和Y的公共子序列。

 

最长公共子序列问题:

给定两个序列X={x1,x2,x3,...,xm}和Y={y1,y2,y3,...,yn},找出X和Y的最长公共子序列

 

动态规划法:

/*
 * 问题描述: 给定两个序列X={x1,x2,x3,...,xm}和Y={y1,y2,y3,...,yn},找出X和Y的最长公共子序列
 * 算法分析:最长公共子序列问题具有最优子结构性质和子问题重叠性质,动态规划法解决
 * 最优值的递归关系:
 * 用c[i][j]记录序列Xi和Yj的最长公共子序列长度
 * 分析:
 * 1)c[i][j] = 0                          i = 0, j = 0;
 * 2)c[i][j] = c[i-1][j-1] + 1            xi = xj;
 * 3)c[i][j] = max{c[i-1][j], c[i][j-1]}  xi != xj
 * 
 * auther:cm
 * date:2010/11/17
 *
 */
public class LcsLength 
{
	private char[] arrX;
	private char[] arrY;
	private int[][] c;

	public LcsLength(String arr1, String arr2)
	{
		arrX = new char[arr1.length() + 1];
		arrY = new char[arr2.length() + 1];
		System.arraycopy(arr1.toCharArray(), 0, arrX, 1, arr1.length());
		System.arraycopy(arr2.toCharArray(), 0, arrY, 1, arr2.length());
		//调用函数
		lcsLength();
	}
	
	//计算最长公共子序列
	public void lcsLength()
	{
		c = new int[arrX.length][arrY.length];
		for (int i = 1; i < arrX.length; i++)
		{
			for (int j = 1; j < arrY.length; j++)
			{
				if (arrX[i] == arrY[j])
				{
					c[i][j] = c[i-1][j-1] + 1;
				}
				else
				{
					c[i][j] = max(c[i-1][j], c[i][j-1]);
				}
			}
		}
	}

	private int max(int m, int n)
	{
		return m > n ? m : n;
	}

	//返回最长子序列
	public String getLCS()
	{
		String lcs = "";
		int i = arrX.length - 1;
		int j = arrY.length - 1;
		while (i >= 1 && j >= 1)
		{
			if (arrX[i] == arrY[j])
			{
				lcs = arrX[i] + lcs;
				i--;
				j--;
			}
			else
			{
				if (c[i][j-1] > c[i-1][j])
				{
					j--;
				}
				else
				{
					i--;
				}
			}
		}
		return lcs;
	}

	public static void main(String[] args) 
	{
		LcsLength lcs = new LcsLength("ABCBDAB", "BDCABA");
		System.out.println(lcs.getLCS());
	}
}

X={A, B, C, B, D, A, B}, Y={B, D, C, A, B, A}.

执行结果:

 

BCBA

 

你可能感兴趣的:(C++,c,C#,zk,J#)