#include <stdio.h> /** * 原题: * 给定两个字符串S和T,求出这两个字符串的最长公共子序列的长度 * 例如X={A,B,C,B,D,A,B},Y={B,D,C,A,B,A} * 则它们的lcs是4 ({B,C,B,A}和{B,D,A,B})。求出一个即可。 */ #define MAX(x,y) (x>y?x:y) #define SL 7 #define TL 6 static char s[SL+2] = " ABCBDAB"; static char t[TL+2] = " BDCABAB"; /** * 思路: * 设置子问题:求s的前i个字符组成的字符串与t的前j个字符组成的字符串的最大公共子序列长度 * 找出边界:显然i或j等于0时,最大公共子序列长度为0 */ //解法1:递归 int solve_1(int i, int j){ if (i == 0 || j == 0) return 0; if (s[i] == t[j]) return MAX(solve_1(i-1, j-1) + 1, MAX(solve_1(i-1, j), solve_1(i, j-1))); return MAX(solve_1(i-1, j), solve_1(i, j-1)); } //解法2:递归+记忆数组 static int memo[SL+1][TL+1]; int solve_2(int i, int j){ if (i == 0 || j == 0) return memo[i][j] = 0; if (memo[i][j] > -1) return memo[i][j]; if (s[i] == t[j]) return memo[i][j] = MAX(solve_2(i-1, j-1) + 1, MAX(solve_2(i-1, j), solve_2(i, j-1))); return memo[i][j] = MAX(solve_2(i-1, j), solve_2(i, j-1)); } //解法3:递推 static int maxLen[SL+1][TL+1]; int solve_3(){ for (int i = 1; i <= SL; ++i) { for (int j = 1; j <= TL; ++j) { if (s[i] == t[j]) maxLen[i][j] = MAX(maxLen[i-1][j-1] + 1, MAX(maxLen[i-1][j], maxLen[i][j-1])); else maxLen[i][j] = MAX(maxLen[i-1][j], maxLen[i][j-1]); } } return maxLen[SL][TL]; } int main() { printf("solve_1:%d\n", solve_1(SL, TL)); for (int i = 0; i <= SL; ++i) { for (int j = 0; j <= TL ; ++j) { memo[i][j] = -1; } } printf("solve_2:%d\n", solve_2(SL, TL)); // for (int i = 0; i <= SL; ++i) { // for (int j = 0; j <= TL ; ++j) { // printf("%d\t", memo[i][j]); // } // printf("\n"); // } printf("solve_3:%d\n", solve_3()); // for (int i = 0; i <= SL; ++i) { // for (int j = 0; j <= TL ; ++j) { // printf("%d\t", maxLen[i][j]); // } // printf("\n"); // } return 0; }
运行结果:
solve_1:4
solve_2:4
solve_3:4