最长公共子序列(LCS)

1. 问题描述:

给定两个字符串(或者是数字序列)A和B,求一个字符串,使得这个字符串是A和B的最长公共部分(子序列可以不连续),例如字符串"sadstory","adminsorry"的最长公共子序列是"adsory",长度为6

2. 思路分析:

① 首先是可以使用暴力破解的,但是在写暴力破解的时候感觉很麻烦,主要是子序列不要求连续导致起点与终点是比较难确定的

② 比较推荐的方法是采用的是动态规划的思想来进行解决的,令dp[i][j]的含义是字符串A的第i个位置与字符串B的第j个位置之前的LCS长度(下标是从1开始的),根据A[i]与B[j]的情况可以分为两种:

1)当A[i]==B[j]时,例如在上面的例子中dp[4][6]表示"sads"与"admins"的LCS长度,比较A[4]与B[6]发现两者都是's'所以dp[4][6]就等于了dp[3][5]的基础上加1,即3

2)当A[i]!=B[j]时,则字符串A的i号位于字符串B的j号位之前的LCS无法延长,因此dp[i][j]或继承dp[i - 1][j]与dp[i][j - 1]的最大值,例如在上面的例子中,dp[3][3]表示"sad"与"adm"的LCS长度,我们比较A[3]与B[3]发现'd'不等于'm'这样dp[3][3]无法在原来的基础上延长,因此继承自"sa"与"adm"的LCS长度与"sad"与"ad"的LCS中的较大值,即"sad"与"ad"的LCS长度是2

3. 下面是具体的代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int n = 100;
char A[n], B[n];
int dp[n][n];
int main(void){
	int n;
	//从下表为1开始读入 
	gets(A + 1);
	gets(B + 1);
	int lenA = strlen(A + 1);
	int lenB = strlen(B + 1);
	//边界 
	for(int i = 0; i <= lenA; ++i){
		dp[i][0] = 0;
	}
	for(int j = 0; j <= lenB; ++j){
		dp[0][j] = 0;
	}
	//状态转移方程
	for(int i = 1; i <= lenA; ++i){
		for(int j = 0; j <= lenB; ++j){
			if(A[i] == B[j]){
				dp[i][j] = dp[i - 1][j - 1] + 1;
			}else{
				dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
			}
		}
	} 
	printf("%d", dp[lenA][lenB]);
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值