动态规划:最长公共子序列

问题描述

我们称序列Z = < z1, z2, ..., zk >是序列X = < x1, x2, ..., xm >的子序列当且仅当存在严格上升的序列< i1, i2, ..., ik >,使得对j = 1, 2, ... ,k, 有xij = zj。比如Z = < a, b, f, c > 是X = < a, b, c, f, b, c >的子序列。

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

输入数据

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

输出要求

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

 

 

解题思路

如果我们用字符数组s1、s2存放两个字符串,用s1[i]表示s1中的第i个字符,s2[j]表示s2中的第j个字符(字符编号从1开始,不存在“第0个字符”),用s1i表示s1的前i个字符所构成的子串, s2j表示s2的前j个字符构成的子串,MaxLen(i, j)表示s1i 和s2j的最长公共子序列的长度,那么递推关系如下:

if( i ==0 || j == 0 ) {

MaxLen(i, j) = 0 //两个空串的最长公共子序列长度当然是0

}

else if( s1[i] == s2[j] )

MaxLen(i, j) = MaxLen(i-1, j-1 ) + 1;

else {

MaxLen(i, j) = Max( MaxLen(i, j-1), MaxLen(i-1, j));

}

 

 

 

 

#define MaxSize 200 #include <stdio.h> #include <string.h> char p[MaxSize+10]; char q[MaxSize+10]; int MaxComLen[MaxSize+10][MaxSize+10]; //MaxComLen[i][j]表示以第一个串第i个元素,第二个串第j个元素为终点的最大公共子串 int main() { int i,j,max; int plen=0,qlen=0; while(scanf("%s%s",p+1,q+1)>0) { int maxlen=0; plen=strlen(p+1); qlen=strlen(q+1); for (i=0;i<=plen;i++) MaxComLen[i][0]=0; for (j=0;j<=qlen;j++) MaxComLen[0][j]=0; //如果i或者j为0,最长公共字串为0 for(i=1;i<=plen;i++) { for (j=1;j<=qlen;j++) { if (p[i]==q[j]) MaxComLen[i][j]=MaxComLen[i-1][j-1]+1;//如果p[i]=q[j],MaxComLen[i][j]=MaxComLen[i-1][j-1]+1 else { if(MaxComLen[i-1][j]>MaxComLen[i][j-1])//如果p[i]!=q[j],MaxComLen[i][j]=MAX(MaxComLen[i][j-1],MaxComLen[i-1][j]) MaxComLen[i][j]=MaxComLen[i-1][j]; else MaxComLen[i][j]=MaxComLen[i][j-1]; } if (MaxComLen[i][j]>maxlen) //输出最大的长度,按照定义应该为最后一个元素 maxlen=MaxComLen[i][j]; } } printf("%d/n",maxlen); } return 0; } 

你可能感兴趣的:(c,测试,zk,任务)