LCS 最长公共子序列(DP经典问题)

最长公共子序列问题以及背包问题都是DP(动态规划)算法的经典题目,值得深度挖掘以致了解DP算法思想。问题如下:

最长公共子序列

时间限制:3000 ms  |  内存限制:65535 KB

难度:3

描述
咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列。

tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。

输入
第一行给出一个整数N(0<N<100)表示待测数据组数

接下来每组数据两行,分别为待测的两组字符串。每个字符串长度不大于1000.

输出
每组测试数据输出一个整数,表示最长公共子序列长度。每组结果占一行。
样例输入
2
asdf
adfsd
123abc
abc123abc
样例输出
3
6

算法分析:根据题意,我们需要找出任意两个字符串中相同的最长序列(不需要1对1完全相同),那么就题中的第一组数据,我们可以起于a也可以起于d或者f,这有着多种不同的情况,所以需用动态规划解决问题,对于LCS可能包含在s与ti-1,也可能存在于si-1与ti中,抑或si与ti之间,这使得我们意识到最后一个相同点就是解题的出发点,存在二种情况:

若s1[i]==s2[j], dp[i][j] = dp[i-1][j-1]+1否则,dp[i][j] = max(dp[i-1][j], dp[i][j-1])

得到DP方程为

一维DP代码如下:

#include <iostream>
#include <cstring>
using namespace std;
char s1[1001], s2[1001];
int dp[1001], t, x, y;
int main(){
	cin>>t;
	while(t--){
		cin>>s1>>s2;
		memset(dp, 0, sizeof(dp));
		int lenS1=strlen(s1), lenS2=strlen(s2);
		for(int i=0; i<lenS1; i++){
			x=0;
			for(int j=0; j<lenS2; j++){
				y = dp[j];
				if(s1[i]==s2[j]) dp[j] = x+1;
				else if(dp[j-1]>dp[j]) dp[j]=dp[j-1];
				x = y;
			}
		}
		cout<<dp[lenS2-1]<<"\n";
	}
	return 0;
}        

二维DP代码如下:

#include <stdio.h>
#include <string.h>
#define MAX 1000
int dp[MAX+1][MAX+1];
char s[MAX],t[MAX];
int max(int a,int b)
{return a>b?a:b;}
int main()
{
	int N,i,j,n,m;
	scanf("%d",&N);
	while(N--)
	{
		scanf("%s%s",s,t);
		int x=strlen(s),y=strlen(t);
		for(i=0;i<x;i++)
		{
			for(j=0;j<y;j++)

				if(s[i]==t[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]);
		}
		printf("%d\n",dp[i][j]);
	}
	return 0;
}

LCS 最长公共子序列(DP经典问题)

时间: 2024-11-11 07:59:10

LCS 最长公共子序列(DP经典问题)的相关文章

lcs(最长公共子序列),dp

lcs(最长公共子序列) 求两个序列的lcs的长度,子序列可不连续 dp[i][j]=dp[i-1][j-1]+1(a[i]==b[i]) dp[i][j]=max(dp[i-1][j],dp[i][j-1])(a[i]!=b[i]) memset(dp,0,sizeof(dp)); for(int i=1;i<=n1;i++){ for(int j=1;j<=n2;j++){ if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(

算法设计 - LCS 最长公共子序列&amp;&amp;最长公共子串 &amp;&amp;LIS 最长递增子序列

出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的最长公共子串方法.最长公共子串用动态规划可实现O(n^2)的时间复杂度,O(n^2)的空间复杂度:还可以进一步优化,用后缀数组的方法优化成线性时间O(nlogn):空间也可以用其他方法优化成线性.3.LIS(最长递增序列)DP方法可实现O(n^2)的时间复杂度,进一步优化最佳可达到O(nlogn)

LCS(最长公共子序列)和dp(动态规划)

参照:v_JULY_v 最长公共子序列定义: 注意最长公共子串(Longest CommonSubstring)和最长公共子序列(LongestCommon Subsequence, LCS)的区别:子串(Substring)是串的一个连续的部分,子序列(Subsequence)则是从不改变序列的顺序,而从序列中去掉任意的元素而获得的新序列:更简略地说,前者(子串)的字符的位置必须连续,后者(子序列LCS)则不必.比如字符串acdfg同akdfc的最长公共子串为df,而他们的最长公共子序列是ad

POJ - 1458 Common Subsequence (LCS最长公共子序列)

题意: 给出两个字符串,求出最长的公共子序列大小. 思路: 算是最经典的LCS问题吧. 设 \(X=(x_1,x_2,.....x_n) 和 Y=(y_1,y_2,.....y_m)\) 是两个序列,将 X 和 Y 的最长公共子序列记为\(lcs(X,Y)\) ,找出\(lcs(X,Y)\)就是一个最优问题 然后我们需要将其分解成子问题并求出子问题的最优解: (寻找子问题来推出当前问题,正是寻找状态转移方程最重要的一步) 1)如果 \(x_n=y_m\),即X的最后一个元素与Y的最后一个元素相同

lightoj 1110 - An Easy LCS 最长公共子序列+string

1110 - An Easy LCS PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB LCS means 'Longest Common Subsequence' that means two non-empty strings are given; you have to find the Longest Common Subsequence between them. Since there

POJ 2250(LCS最长公共子序列)

compromise Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfilled, and this is n

LIS(最长递增子序列)和LCS(最长公共子序列)的总结

最长公共子序列(LCS):O(n^2) 两个for循环让两个字符串按位的匹配:i in range(1, len1) j in range(1, len2) s1[i - 1] == s2[j - 1], dp[i][j] = dp[i - 1][j -1] + 1; s1[i - 1] != s2[j - 1], dp[i][j] = max (dp[i - 1][j], dp[i][j - 1]); 初始化:dp[i][0] = dp[0][j] = 0; 伪代码: dp[maxn1][ma

hdu 1159 Common Subsequence(最长公共子序列 DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159 Common Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 25416    Accepted Submission(s): 11276 Problem Description A subsequence of

hdu 1159 common sequence (最长公共子序列 dp)

http://acm.hdu.edu.cn/showproblem.php?pid=1159 题意 : 给出两个字符串 求出最长公共子序列 思路: if(str1[i]==str2[j]) { dp[i][j]=max(dp[i-1][j-1]+1,max(dp[i-1][j],dp[i][j-1])); } else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); #include<cstdio> #include<cstring> #include&l