NYOJ 36 最长公共子序列

来源:互联网 发布:unix编程入门课程知乎 编辑:程序博客网 时间:2024/05/16 17:25

最长公共子序列

时间限制:3000 ms  |  内存限制:65535 KB
难度:3
描述
咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列。
tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。
输入
第一行给出一个整数N(0<N<100)表示待测数据组数
接下来每组数据两行,分别为待测的两组字符串。每个字符串长度不大于1000.
输出
每组测试数据输出一个整数,表示最长公共子序列长度。每组结果占一行。
样例输入
2asdfadfsd123abcabc123abc
样例输出
36

 

/*求最长公共子序列。动态规划问题。

  设序列X = (x1; x2; . . . ; xm) 和Y =(y1; y2; . . . ; yn) 的最长公共子序列为
  Z = (z1; z2; . . . ; zk),

. 若xm = yn,则zk = xm = yn,且Zk-1 是Xm-1 和Yn-1 的最长公共子序列。
. 若xm != yn 且zk != xm,则Z 是Xm-1 和Y 的最长公共子序列。
. 若xm != yn 且zk != yn,则Z 是X 和Yn-1 的最长公共子序列。

  其中Xm-1 = (x1; x2; . . . ; xm-1), Yn-1 = (y1; y2; . . . ; yn-1), Zk-1 = (z1; z2; . . . ; zk-1)
*/

一般解法,不优化空间。

 #include <stdio.h>#include <string.h>#define MAX 1010int dp[MAX][MAX] = {0};void lcs(const char *x, int m, const char *y, int n){int i,j;for (i=0; i<=m; i++){dp[i][0] = 0;}for (j=0;j<=n; j++){dp[0][j] = 0;}for (i=1; i<=m; i++){for (j=1; j<=n; j++){if (x[i-1] == y[j-1]){dp[i][j] = dp[i-1][j-1] + 1;}else{dp[i][j] = dp[i-1][j] > dp[i][j-1]?dp[i-1][j] : dp[i][j-1];}}}}int main(){int m;char x[MAX],y[MAX];scanf("%d",&m);while (m--){int xlen,ylen;scanf("%s%s",x,y);xlen = strlen(x);ylen = strlen(y);lcs(x,xlen,y,ylen);printf("%d\n",dp[xlen][ylen]);}return 0;}        


 

滚动数组,优化空间

 

 #include <stdio.h>#include <string.h>#define MAX 1001short dp[2][MAX];int main(){int m;char x[MAX],y[MAX];scanf("%d",&m);while (m--){int xlen,ylen;int i,j,e = 0;scanf("%s%s",x,y);xlen = strlen(x);ylen = strlen(y);memset(dp,0,sizeof(dp));for (i=1; i<=xlen;i++){e = 1-e;for (j=1; j<=ylen; j++){if (x[i-1] == y[j-1]){dp[e][j] = dp[1-e][j-1] + 1;}else{dp[e][j] = dp[e][j-1] > dp[1-e][j]?dp[e][j-1] : dp[1-e][j];}}}printf("%d\n",dp[e][ylen]);}return 0;}        


 

0 0