动态规划----最长公共子序列(C++实现)

最长公共子序列

  • 题目描述:给定两个字符串s1 s2 … sn和t1 t2 … tm 。求出这两个字符串的最长公共子序列的长度。字符串s1 s2 … sn的子序列指可以表示为s_{i1}s_{i2}s_{i k} { i1 < i2 < … < ik }的序列。
  • 输入样例

       2
       asdf
       adfsd
       123abc
       abc123abc

  • 输出样例

        3

        6

  • 解题思路:

这道题是被称为最长公共子序列的问题(LCS,Longest Common Subsequence)的著名问题。这道题我们是用动态规划的思想来做的。我们先拿第一组测试用例,asdf 与 adfsd 作为例子来看一下这道题的思路。上图!!

j / i01(a)2(s)3(d)4(f)
000000
1(a)01111
2(d)01122
3(f)01123
4(s)01223
5(d)01223

做这种题,我们要用一个二维数组(dp[MAX_N][MAX_N])来存放每一个状态的值。如图所示,横向代表i、纵向代表j,那么,每一个网格的值是怎么来的呢。在这里我们把每一个状态即dp[i][j] 看做 s1 … si 和 t1 … tj 的LCS的长度。由此我们,s1 … s(i+1) 和 t1 … t(j+1) 对应的公共子列长度可能是:

当s(i+1) == t(j+1),在 s1 … si 和 t1 … tj 的公共子列末尾追加上s(i+1) 。

否则则可能是 s1 … si 和 t1 … t(j+1) 的公共子列或者 s1 … s(i+1) 和 t1 … tj 的公共子列最大值。

对应下面的公式:

有了上面的公式我们就可以写代码了:

//最长公共子序列
#include<iostream>
#include<string>
#include<cstring>
#define MAX 1001 
using namespace std;
int dp[MAX][MAX];
int main()
{
	int N;
	cin >> N;
	while(N--)
	{
		string a,b;
		cin >> a >> b;
		memset(dp,0,sizeof(dp));
		int len_a=a.size(),len_b=b.size(); 
		for(int i=0;i<len_a;i++)
		{
			for(int j=0;j<len_b;j++)
			{
				if(a.at(i)==b.at(j))
					dp[i+1][j+1]=dp[i][j]+1;
				else 
					dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);
			}
		}
		cout << dp[len_a][len_b] << endl;
		a.clear();
		b.clear();
	}
	return 0;
}

 

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值