码迷,mamicode.com
首页 > 其他好文 > 详细

最长公共子序列

时间:2016-05-12 20:28:16      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:

题目

给定两个字符串str1和str2,返回两个字符串的最长公共子序列。

举例:

str1="1A2C3D4B56",str2="B1D23CA45B6A"

“123456”和"12C4B6"都是最长公共子序列,返回哪一个都行。

分析

经典动态规划,求解二维动态规划表。假设str1的长度为m,str2的长度为n,声明大小为m*n的矩阵dp,行数为m,列数为n。dp[i][j]的含义是str1[0...i]和str2[0...j]的最长公共子序列长度,从左向右,从上到下计算矩阵dp。

具体步骤见《程序员代码面试指南》P210

代码

/*
4.7 给定两个字符串str1和str2,返回两个字符串的最长公共子序列。
*/

#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

/*计算动态规划矩阵*/
vector<vector<int>> getDp(string A, string B)
{
	if (A.empty() || B.empty())
	{
		return vector<vector<int>>();
	}//if

	int aLen = A.size(), bLen = B.size();

	/*矩阵dp[i][j]的含义是字符串A[0...i]与字符串B[0...j]的最长公共子序列长度,从左到右,从上到下计算矩阵dp*/
	vector<vector<int>> dp(aLen, vector<int>(bLen, 0));
	dp[0][0] = A[0] == B[0] ? 1 : 0;
	for (int i = 1; i < aLen; ++i)
	{
		dp[i][0] = max(dp[i - 1][0], A[i] == B[0] ? 1 : 0);
	}//for

	for (int j = 1; j < bLen; ++j)
	{
		dp[0][j] = max(dp[0][j], A[0] == B[j] ? 1 : 0);
	}//for

	for (int i = 1; i < aLen; ++i)
	{
		for (int j = 1; j < bLen; ++j)
		{
			dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

			if (A[i] == B[j])
			{
				dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
			}//if
		}//for
	}//for

	/*此时dp[aLen-1][bLen-1]便是最长公共子序列的长度*/
	return dp;
}

/*求最长公共子序列*/
string longestCommonSubsequence(string str1, string str2)
{
	if (str1.empty() || str2.empty())
	{
		return "";
	}//if

	/*得到最长公共子序列长度的动态规划长度矩阵*/
	vector<vector<int>> dp = getDp(str1, str2);

	int m = str1.length() - 1, n = str2.length() - 1, len = dp[m][n];
	/*最长公共子序列长度为len,初始化一个结果字符串*/
	string ret(len,'0');
	/*从右下角遍历矩阵*/
	for (int idx = len - 1; idx >= 0; )
	{
		if (n > 0 && dp[m][n] == dp[m][n - 1])
		{
			/*不选str1[m] 和 str2[n] 向左移动*/
			--n;
		}//if
		else if (m > 0 && dp[m][n] == dp[m - 1][n])
		{
			/*不选str1[m] 和 str2[n] 向上移动*/
			--m;
		}//elif
		else {
			/*选择当前字符,向左上方移动*/
			ret[idx--] = str1[m];
			--m;
			--n;
		}//else
	}//for

	return ret;
}

int main()
{
	string str1 = "1A2C3D4B56", str2 = "B1D23CA45B6A";
	cout << longestCommonSubsequence(str1, str2) << endl;

	system("pause");
	return 0;
}
GitHub代码

最长公共子序列

标签:

原文地址:http://blog.csdn.net/fly_yr/article/details/51356306

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!