数据结构与算法之最长公共子序列
最长公共子序列(LCS)是指给定两个序列X和Y,找出一个最长的子序列既是X的子序列也是Y的子序列。子序列是指在序列中删去任意个元素而不改变其他元素顺序得到的新序列。
LCS问题可以使用动态规划求解。假设x[1…m]和y[1…n]是两个序列,令c[i,j]表示x[1…i]和y[1…j]的LCS长度,则有以下状态转移方程:
- 当i=0或j=0时,c[i,j]=0;
- 当x[i]=y[j]时,c[i,j]=c[i-1,j-1]+1;
- 当x[i]!=y[j]时,c[i,j]=max(c[i,j-1],c[i-1,j])。
根据上述方程,可以使用一个二维数组c来存储每个子问题的解,从而只需要计算一次就可以在O(mn)的时间复杂度内求出LCS的长度。
求出LCS的长度之后,可以通过回溯求出具体的LCS序列。从c[m,n]开始,不断向左上方移动,如果x[i]=y[j],则将x[i]加入LCS序列中,直到回溯到c[0,0]为止。
一、C 实现 最长公共子序列 及代码详解
下面是 C 语言实现最长公共子序列的代码:
#include <stdio.h>
#include <string.h>
#define MAX_LEN 100
int max(int a, int b) {
return a > b ? a : b;
}
void lcs(char *s1, char *s2, int m, int n) {
int dp[MAX_LEN][MAX_LEN];
int i, j, k;
memset(dp, 0, sizeof(dp));
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++) {
if (s1[i-1] == s2[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
printf("Length of LCS: %d\n", dp[m][n]);
char lcs[MAX_LEN];
k = dp[m][n];
i