最长公共子序列 LCS

定义

longest common subsequence:给定两个序列S1和S2,求二者公共子序列S3的最长的长度。

//注意不是最大公共子串

分析

这个问题可以按照序列的长度来划分状态,也就是S1的前i个字符和S2的前j个字符的最长公共子序列长度,记为lcs[i][j]。

如果S1的第i项,和S2的第j项相同,那么S1[i]与S2[j]作为公共子序列的末尾,则

lcs[i][j] = lcs [ i-1 ] [ j-1 ]+1

也可以不让S1[i]与S2[j]作为公共子序列的末尾,则

lcs[i][j] = max(lcs[ i ] [ j -1 ], lcs[ i-1 ] [ j ])

注意:这种方法考虑的是到某一位(i, j)为止,而不一定是以它结尾

 

关于不相等的转移方程:可以这么理解:既然两个位置不等,那么就求这两个位置之前的一个最大值,而显然,越靠近这两个位置的值越大,那么就取各自减1的位置就行了。

这个不相等时的转移方程是一定要有的,因为不像最大公共子串维护了一个最大值,一旦不相等了不需要看前面的累计,不需要任何处理,继续往下走就行;这里是求子序列,序列是可以不连续的,所以必须每个点都要存值。

int dp[10][10];

int main(){
	
	string a, b;
	cin >> a >> b;
	int lena = a.length();
	int lenb = b.length();
	for(int i = 0; i < lena; i++){
		for(int j = 0; j < lenb; j++){
			if(a[i] == b[j])
				dp[i+1][j+1] = dp[i][j] + 1;
			else 
				dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j]);
		}
	}
    //输出dp数组,最后一个值即为答案
	for(int i = 1; i < lena+1; i++){
		for(int j = 1; j < lenb+1; j++)
			cout << dp[i][j] << " ";
		cout << endl;
	}
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值