动态规划解LCS问题

今天研究了一下动态规划,思想很简单:循序渐进,局部推到整体。但运用起来还是不太好想的。

下面用动态规划解LCS最大公共子串问题

写了两个函数LCS和LCS_Inhance,前者用矩阵实现(用于理解原理),后者用两个数组实现(节省空间)。

由于初学,不做过多评论,已免误导读者。

代码如下:

#include<iostream>
#include<string>
using namespace std;
int max(int x, int y, int z){
	if (x > y)
		return x > z ? x : z;
	else
		return y > z ? y : z;
}
int LCS(const string& s1,const string& s2){//用矩阵,暂用空间大

	if (s1.empty() || s2.empty())
		return 0;
	int len_min = s1.size() <= s2.size() ? s1.size() : s2.size();
	int **map = new int*[s1.size()];
	for (int i = 0; i < s1.size(); ++i)
		map[i] = new int[s2.size()];

	for (int i = 0; i < s1.size(); ++i){
		if (s1[i] == s2.front()){
			for (; i < s1.size(); ++i)
				map[i][0] = 1;
			break;
		}
		map[i][0] = 0;
	}
	for (int i = 0; i < s2.size(); ++i){
		if (s1.front() == s2[i]){
			for (; i < s2.size(); ++i)
				map[0][i] = 1;
			break;
		}
		map[0][i] = 0;
	}
	
	for (int i = 1; i < len_min; ++i){
		for (int j = i; j < s1.size(); ++j){
			if (s1[j] == s2[i])
				map[j][i] = max(map[j][i - 1], map[j - 1][i], map[j - 1][i - 1] + 1);
			else
				map[j][i] = max(map[j][i - 1], map[j - 1][i], map[j - 1][i - 1] );
		}
		for (int j = i; j < s2.size(); ++j){
			if (s1[i] == s2[j])
				map[i][j] = max(map[i - 1][j], map[i][j - 1], map[i - 1][j - 1] + 1);
			else
				map[i][j] = max(map[i - 1][j], map[i][j - 1], map[i - 1][j - 1] );
		}
	}
	int tep= map[s1.size() - 1][s2.size() - 1];
	for (int i = 0; i < s1.size(); ++i)
		delete[] map[i];
	return tep;
}

int LCS_Inhance( char* s1, char* s2){//用两个数组,暂用空间小,关键是需要用一个temp存储斜对角的元素,以免写时覆盖
	if (strlen(s1) == 0 || strlen(s2) == 0)
		return 0;
	if (strlen(s1)>strlen(s2)){
		s1 = (char*)((int)s1 ^ (int)s2);
		s2 = (char*)((int)s1 ^ (int)s2);
		s1 = (char*)((int)s1 ^ (int)s2);
	}
	int h = strlen(s1);
	int l = strlen(s2);
	int *pl = new int[l];
	int *ph = new int[h];
	for (int i = 0; i < l; ++i){
		if (s1[0] == s2[i]){
			for (; i < l; ++i)
				pl[i] = 1;
			break;
		}
		pl[i] = 0;
	}
	for (int i = 0; i < h; ++i){
		if (s2[0] == s1[i]){
			for (; i < h; ++i)
				ph[i] = 1;
			break;
		}
		ph[i] = 0;
	}
	for (int i = 1; i < h; ++i){
		int temp1,temp2;
		temp1 = pl[i];
		temp2 = ph[i];
		if (s1[i] == s2[i]){
			pl[i] = max(ph[i], pl[i], pl[i - 1] + 1);
			ph[i] = max(pl[i], ph[i], ph[i - 1] + 1);
		}
		else{
			pl[i] = max(ph[i], pl[i], pl[i - 1] );
			ph[i] = max(pl[i], ph[i], ph[i - 1] );
		}
		for (int j = i+1; j < l; ++j){
			if (s2[j] == s1[i]){
				int temp = max(temp1 + 1, pl[j], pl[j - 1]);
				temp1 = pl[j];
				pl[j] = temp;
			}
			else{
				int temp = max(temp1, pl[j], pl[j - 1]);
				temp1 = pl[j];
				pl[j] = temp;
			}
		}
		for (int j = i + 1; j < h; ++j){
			if (s2[j] == s1[i]){
				int temp = max(temp2 + 1, ph[j], ph[j - 1]);
				temp2 = ph[j];
				ph[j] = temp;
			}
			else{
				int temp = max(temp2, ph[j], ph[j - 1]);
				temp2 = ph[j];
				ph[j] = temp;
			}
		}
	}
	//cout << pl[l - 1] << '\t' << ph[h - 1] << endl;
	int result = pl[l - 1];
	delete[] pl, ph;
	return result;
}
int main(){
	FILE* pf;
	freopen_s(&pf, "c:\\acm_input.txt", "r",stdin);
	string s1, s2;
	int input_num = 4;
	for (int i = 0; i < input_num; ++i){
		cin >> s1 >> s2;
		cout << LCS(s1, s2) << endl;

		char *ps1 = new char[s1.size() + 1];
		char *ps2 = new char[s2.size() + 1];
		ps1[s1.size()] = '\0';
		ps2[s2.size()] = '\0';
		strncpy(ps1, s1.c_str(), s1.size());
		strncpy(ps2, s2.c_str(), s2.size());
		cout<<LCS_Inhance(ps1, ps2)<<endl;
		delete[] ps1, ps2;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值