E

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;
}
原文地址:https://www.cnblogs.com/luoxiaoyi/p/13848034.html