最长公共子序列
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列。
tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。-
输入
-
第一行给出一个整数N(0<N<100)表示待测数据组数
接下来每组数据两行,分别为待测的两组字符串。每个字符串长度不大于1000.
输出
- 每组测试数据输出一个整数,表示最长公共子序列长度。每组结果占一行。 样例输入
-
2 asdf adfsd 123abc abc123abc
样例输出
-
3 6
来源
- 经典 上传者
-
hzyqazasdf
思路:动态规划问题,由基本思想可知,问题的最优解是由子问题的最优解构成的,所以lcs(i,j) 的值与lcs(i-1, j-1), lcs(i-1, j), lcs(i, j-1) 有一定的关系。例如: x[7] = "123abc"y[7] = "abc123abc"首先将问题划分,利用双层for循环:第一层for循环如同先缩短x的长度,求x[0...i]与y的最长公共字串长度len1,然后i+1,再求x[0...i+1]与y的最长公共子串长度len2,此时,显然len2最小=len1,最大等于len1+1;而第二层for循环相当于缩短y的长度,求x[0..i]与y[0..j]的最长公共子串leny1, 然后j +1,与上同理。最终lcs[lenx][leny]的值即为x,y最长子串的长度!for(i = 1; i <= xs; ++i){
for(j = 1;j <= ys; ++j){……}
}
(图中红字代表x,y从第一个元素到该元素,例如lcs[4,5]的值代表“123a”与“abc12”的最长公共子串长度);
要确定lcs(i,j)的值,需要首先比较一下x[i], y[j] 的值:
1) 当x[i] == y[j]时,说明x[i]与y[j] 一定在最长公共子序列中,而lcs (i , j) 的值为lcs(i-1,j-1)的值 + 1(因为最长公共子串不要求连续);
2) 当x[i] != y[j]时 ,lcs(i, j)的值=max(lcs(i - 1, y), lcs(i, y - 1));由以上解释,此题也可用递归算法解决,不过提交超时,一并附上代码
动态规划代码:
#include <stdio.h> #include <string> #define N 1001 int lcs[N][N]; int max(int a, int b){ return a > b ? a : b; } int main() { int n, i, j; char x[N], y[N]; scanf("%d", &n); while(n --){ scanf(" %s %s", x, y); int lenx = strlen(x); int leny = strlen(y); for(i = 0; i <= lenx; i ++) lcs[i][0] = 0; for(i = 1; i <= leny; i ++) lcs[0][i] = 0; for(i = 1; i <= lenx; i ++){ for(j = 1;j <= leny; j ++){ lcs[i][j] = (x[i - 1] == y[j - 1]) ? (lcs[i - 1][j - 1] + 1) : max(lcs[i - 1][j], lcs[i][j - 1]); } } /*for(i = 0; i <= lenx; i ++){ for(j = 0; j <= leny; j ++){ printf("%d ", lcs[i][j]); } printf("\n"); }*/ printf ("%d\n", lcs[lenx][leny]); } return 0; }
#include <stdio.h> #include <string.h> #define N 1001 char x[N], y[N]; int max(int a, int b){ return a > b ? a : b; } int f(int lenx, int leny) { if(lenx == 0 || leny == 0) return 0; if(x[lenx - 1] == y [leny - 1]) return 1 + f(lenx - 1, leny - 1); else return max(f(lenx - 1, leny), f(lenx, leny - 1)); } int main() { int n, lenx, leny, ans; scanf("%d", &n); while(n --){ scanf(" %s %s", x, y); lenx = strlen(x); leny = strlen(y); ans = f(lenx, leny); printf("%d\n", ans); } return 0; }
-
第一行给出一个整数N(0<N<100)表示待测数据组数