算法导论第15章 最长公共子序列问题(LCS)

最长公共子序列问题:

给定两个两个序列X= <x1, x2, ....., xm>和Y = <y1, y2, ...., yn>,希望找出X和Y的最大长度的公共子序列,可以使用动态规划来解决

定理15.1(LCS的最优子结构)
设X= <x1, x2, ....., xm>和Y = <y1, y2, ...., yn>为两个序列,并设Z = {z1, z2, ....,zk}为X和Y的任意一个LCS
(1)如果xm = yn, 那么zk = xm = yn, 而且Zk-1是Xm-1与Yn-1的一个LCS
(2)如果xm != yn,那么Zk != xm蕴含Z是Xm-1和Y的一个LCS
(3)如果xm != yn, 那么Zk != yn,蕴含Z是X和Yn-1的一个LCS 

定义c[i][j]为序列Xi与Yi的一个LCS长度,则有下面递归表达式
              0                                     若i = 0 或 j = 0;
c[i][j] =  c[i-1][j-1]+1                    若i, j > 0 且xi = yi;
             max(c[i][j-1], c[i-1][j])     若i,j > 0 且 xi != yi;
根据上面的递归式可以写出自底向上的动态规划代码

#include <iostream>
using namespace std;

const int m = 8;
const int n = 7;

//返回值结构
struct twoArrayPair
{
	char b[m][n];
	int c[m][n];
};

/*************************************************************/
/*
c[m][n]:保存了X和Y的LCS长度
b[m][n]: 帮助构造最优解

           0                          若i = 0 或 j = 0;
c[i][j] =  c[i-1][j-1]+1              若i, j > 0 且xi = yi;
           max(c[i][j-1], c[i-1][j])  若i,j > 0 且 xi != yi;
*/
/*************************************************************/
twoArrayPair *LCSLength(char *x,a char *y)
{
	twoArrayPair *twoArray = new twoArrayPair;

	//c, b数组初始化
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
		{
			(twoArray->b)[i][j] = ' ';
			(twoArray->c)[i][j] = 0;
		}
	}

	for (int i = 1; i < m; i++)
	{
		for (int j = 1; j < n; j++)
		{
			if (x[i] == y[j])
			{
				(twoArray->c)[i][j] = (twoArray->c)[i-1][j-1]+1;
				(twoArray->b)[i][j] = '\\';
			}
			else if ((twoArray->c)[i-1][j] >= (twoArray->c)[i][j-1])
			{
				(twoArray->c)[i][j] = (twoArray->c)[i-1][j];
				(twoArray->b)[i][j] = '|';
			}
			else
			{
				(twoArray->c)[i][j] = (twoArray->c)[i][j-1];
				(twoArray->b)[i][j] = '-';
			}
		}
	}
	return twoArray;
}

//打印LCS
void printLCS(char (*b)[n], char *x, int i, int j)
{
	if (i == 0 | j == 0)
	   return;
	if (b[i][j] == '\\')
	{
		printLCS(b, x, i-1, j-1);
		cout << x[i];
	}
	else if (b[i][j] == '|')
	    printLCS(b, x, i-1, j);
	else
		printLCS(b, x, i, j-1);
}

int main()
{
	char x[] = "0ABCBDAB";
	char y[] = "0BDCABA";

	twoArrayPair *tt = LCSLength(x, y);
	cout << "x与y的最长公共子序列是:" << endl;
	printLCS(tt->b, x, m-1, n-1);
	cout << endl;

	system("pause");
	return 0;
}

运行结果为:
算法导论第15章 最长公共子序列问题(LCS)_第1张图片

你可能感兴趣的:(算法导论第15章 最长公共子序列问题(LCS))