Description
给定两个序列 X={x1,x2,…,xm} 和 Y={y1,y2,…,yn},找出X和Y的最长公共子序列。
Input
输入数据有多组,每组有两行 ,每行为一个长度不超过500的字符串(输入全是大写英文字母(A,Z)),表示序列X和Y。
Output
每组输出一行,表示所求得的最长公共子序列的长度,若不存在公共子序列,则输出0。
Sample
Input
ABCBDAB
BDCABA
Output
4
题解:
最长公共子序列(LCS)。
首先,从一个给定的串中删去(不一定连续地删去)0个或0个以上的字符,剩下地字符按原来顺序组成的串。例如:“ ”,“a”,“xb”,“aaa”,“bbb”,“xabb”,“xaaabbb”都是串“xaaabbb”的子序列。(例子中的串不包含引号。)
若s1[i] = s2[j]时,那么当前字母一定是某个公共子序列的尾字母,那么只要寻找s1与S2去掉当前字母的公共最长公共子序列+1(LCS(i-1, j-1)+1)就是当前两个字符串的最长公共子序列。
若s1[i] ≠ s2[j]时,那么当前最长公共子序列为max(LCS(i-1,j),LCS(i,j-1))。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define maxn 505
using namespace std;
/**
*s1 s2分别存储两个字符串。
*/
char s1[maxn],s2[maxn];
/**
*dp当前最大公共子序列
*/
int dp[maxn][maxn];
/**
*LCS()求最长公共子序列的函数
*i s1当前的游标。
*j s2当前的游标。
*/
int lcs(int i,int j){
if(dp[i][j] != -1)
return dp[i][j];
//若有一方为0既当前有一个字符串长度为0.则公共子序列也为0;
if(i==0||j==0){
dp[i][j] = 0;
}
//若s1[i] = s2[j]时,那么当前字母一定是某个公共子序列的尾字母,
//那么只要寻找(LCS(i-1, j-1)+1)就是当前两个字符串的最长公共子序列。
else if(s1[i - 1] == s2[j - 1]){
dp[i][j] = lcs(i - 1, j - 1) + 1;
}
//若s1[i] ≠ s2[j]时,那么当前最长公共子序列为
//max(LCS(i-1,j),LCS(i,j-1))。
else{
dp[i][j] = max(lcs(i - 1, j), lcs(i, j - 1));
}
return dp[i][j];
}
int main()
{
/**
*l1字符串1的长度
*l2字符串2的长度
*/
int l1,l2;
while(scanf("%s%s",s1,s2)!=EOF){
memset(dp,-1,sizeof(dp));
l1 = strlen(s1);
l2 = strlen(s2);
printf("%d
",lcs(l1,l2));
}
return 0;
}