最长公共子序列(LCS)

题目描述

我们称序列$Z=\left \langle z_{1},z_{2},...,z_{k}\right \rangle$是序列$X=\left \langle x_{1},x_{2},...,x_{m}\right \rangle$的子序列当且仅当存在 严格上升 的序列$\left \langle i_{1},i_{2},...,i_{k}\right \rangle$,使得对$j=1,2,...,k$,有$x_{i_{j}}=z_{j}$。比如$Z=\left \langle a,b,f,c\right \rangle$是$X=\left \langle a,b,c,f,b,c\right \rangle$的子序列

现在给出两个序列$X$和$Y$,你的任务是找到$X$和$Y$的最大公共子序列,也就是说要找到一个最长的序列$Z$,使得$Z$既是$X$的子序列也是$Y$的子序列。

输入格式

输入包括多组测试数据。每组数据包括一行,给出两个长度不超过$200$的字符串,表示两个序列。两个字符串之间由若干个空格隔开。

输出格式

对每组输入数据,输出一行,给出两个序列的最大公共子序列的长度。

样例数据

输入

abcfbc         abfcab
programming    contest 
abcd           mnp

输出

4
2
0

分析

如果$A_{i}=B_{j}$的话,那么$Dp_{i,j}=Dp_{i-1,j-1}+1$,其中$Dp_{i,j}$表示序列$A$在第$i$个元素之前与序列$B$在第$j$个元素之前最长公共子序列的长度

状态转移方程

代码

#include <bits/stdc++.h>

#define Enter puts("")
#define Space putchar(' ')

using namespace std;

typedef long long ll;
typedef double Db;

inline ll Read() 
{
    ll Ans = 0;
    char Ch = getchar() , Las = ' ';
    while(!isdigit(Ch)) 
    {
        Las = Ch;
        Ch = getchar();
    }
    while(isdigit(Ch)) 
    {
        Ans = (Ans << 3) + (Ans << 1) + Ch - '0';
        Ch = getchar();
    }
    if(Las == '-')
        Ans = -Ans;
    return Ans;
}

inline void Write(ll x) 
{
    if(x < 0) 
    {
        x = -x;
        putchar('-');
    }
    if(x >= 10)
        Write(x / 10);
    putchar(x % 10 + '0');
}

char a[1001] , b[1001];
int Dp[1001][1001];
int main() 
{
    while(~scanf("%s%s" , a + 1 , b + 1)) 
    {
        int n = strlen(a + 1);
        int m = strlen(b + 1);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; 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]);
        Write(Dp[n][m]) , Enter;
        memset(Dp , 0 , sizeof(Dp));
    }
    return 0;
}

 

posted @ 2021-04-29 20:46  Tenderfoot  阅读(101)  评论(0编辑  收藏  举报