最长公共子序列

 

算法题2 最长公共子序列

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 36  Solved: 13

Description

序列Z=<B,C,D,B>是序列X=<A,B,C,B,D,A,B>的子序列,相应的递增下标序列为<2,3,5,7>。

一般地,给定一个序列X=<x1,x2,…,xm>,则另一个序列Z=<z1,z2,…,zk>是X的子序列,是指存在一个严格递增的下标序列〈i1,i2,…,ik〉使得对于所有j=1,2,…,k使Z中第j个元素zj与X中第ij个元素相同。

给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。

你的任务是:给定2个序列X、Y,求X和Y的最长公共子序列Z。

Input

输入文件中的第1行是一个正整数T,(0<T<=10),表示有T组测试数据。接下来是每组测试数据的描述,每组测试数据有3行。

测试数据的第1行有2个正整数m、n,中间用一个空格隔开,(0<m,n<50);第2、3行是长度分别为m、n的2个序列X和Y,每个序列的元素间用一个空格隔开。序列中每个元素由字母、数字等构成。

输入直到文件结束。

Output

对输入中的每组测试数据,输出2行。先在一行上输出“Case #”,其中“#”是测试数据的组号(从1开始),再在第2行上输出这2个序列X、Y的最长公共子序列Z的长度。

Sample Input

2
7 6
A B C B D A B
B D C A B A
8 9
b a a b a b a b
a b a b b a b b a

Sample Output

Case 1
4
Case 2
6
代码:
#include<stdio.h> 
#include<string.h> 
#define Maxn 110 
int c[Maxn][Maxn]; 
char str1[Maxn],str2[Maxn]; 
int m,n; 
void LCS() 
{ 
    int i,j; 
    for(i=1;i<=n;i++) c[0][i]=0;  //初始化边界值 
    for(i=0;i<=m;i++) c[i][0]=0; 
    for(i=1;i<=m;i++)   //自顶而下动态规划 
        for(j=1;j<=n;j++) 
            if(str1[i]==str2[j])  c[i][j]=c[i-1][j-1]+1; 
            else if(c[i-1][j]>=c[i][j-1])  c[i][j]=c[i-1][j]; 
            else  c[i][j]=c[i][j-1]; 
} 
int main() 
{ 
    int t,i,j,k; 
    char s[1000]; 
    scanf("%d",&t); 
    for(i=0;i<t;i++){ 
        scanf("%d%d",&m,&n);  //m为行,n为列 
        getchar(); 
            k=0; 
    for(j = 0; j < m; j++) { 
      scanf("%s",s); 
      str1[++k] = s[0]; 
    } 
    k = 0; 
    for(j = 0; j < n; j++) { 
      scanf("%s",s); 
      str2[++k] = s[0]; 
    } 
        LCS(); 
        printf("Case %d\n%d\n",i+1,c[m][n]); 
    } 
    return 0; 
} 
注:传说中LCS。状态转移方程:
f[i][j]=f[i-1][j-1]+1 str1[i]==str2[j]
f[i][j]=max{f[i-1][j],f[i][j-1]} str1[i]!=str2[j]
初始条件:f[0][i]=0(0<=i<=n),f[j][0]=0(0<j<=m)

你可能感兴趣的:(最长公共子序列)