Longest Common Subsequence

来源:互联网 发布:网络装修平台有哪些 编辑:程序博客网 时间:2024/05/20 13:15

Longest Common Subsequence

最長共通部分列

最長共通部分列問題 (Longest Common Subsequence problem: LCS)は、2つの与えられた列 X={x1,x2,...,xm}Y={y1,y2,...,yn} の最長共通部分列を求める問題です。

ある列 ZXY 両方の部分列であるとき、ZXY の共通部分列と言います。例えば、X={a,b,c,b,d,a,b}, Y={b,d,c,a,b,a} とすると、列 {b,c,a}XY の共通部分列です。一方、列 {b,c,a}XY の最長共通部分列ではありません。なぜなら、その長さは 3 であり、長さ 4 の共通部分列 {b,c,b,a} が存在するからです。長さが 5 以上の共通部分列が存在しないので、列 {b,c,b,a}XY の最長共通部分列の1つです。

与えられた2つの文字列 XYに対して、最長共通部分列 Z の長さを出力するプログラムを作成してください。与えられる文字列は英文字のみで構成されています。
入力

複数のデータセットが与えられます。最初の行にデータセットの数 q が与えられます。続く 2×q 行にデータセットが与えられます。各データセットでは2つの文字列 X, Y がそれぞれ1行に与えられます。

出力

各データセットについて X, Y の最長共通部分列 Z の長さを1行に出力してください。

制約

1q150
1X,Y1,000
X または Y の長さが 100 を超えるデータセットが含まれる場合、q は 20 以下である。

入力例 1

3
abcbdab
bdcaba
abc
abc
abc
bc

出力例 1

4
3
2

参考文献

Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. The MIT Press.

解题思路:
本题是一个裸的LCS,动态转移方程如下

s1[i1]==s2[j1]dp[i][j]=dp[i1][j1]+1
否则dp[i][j]=max(dp[i1][j],dp[i][j1])
i和j表示序列一的前i个字符和序列二的前j个字符的最长公共子序列的长度为dp[i][j]

代码如下:

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1050;char s1[maxn],s2[maxn];int f[maxn][maxn];int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%s%s",s1,s2);        int len1 = strlen(s1);        int len2 = strlen(s2);        memset(f,0,sizeof(f));        for(int i = 0;i <= len1; i++)        {            for(int j = 0;j <= len2; j++)            {                if(i == 0 || j == 0)f[i][j] = 0;                else                {                    if(s1[i-1] == s2[j-1])f[i][j] = f[i-1][j-1] + 1;                    else f[i][j] = max(f[i-1][j],f[i][j-1]);                }            }        }        printf("%d\n",f[len1][len2]);    }}
0 0