c语言最长公共子序列自顶向下和自底向上
时间: 2024-06-18 08:05:28 浏览: 115
最长公共子序列(Longest Common Subsequence,简称LCS)是指两个或多个序列中的最长公共子序列,可以使用动态规划求解。
自顶向下的方法也被称为记忆化搜索,它使用递归来实现。我们将问题划分为子问题,并将其存储在一个数组中。在计算过程中,先检查存储的数组是否有对应的值,如果没有,则计算它并将其存储在数组中,然后返回该值。这种方法可以避免重复计算相同的子问题,从而提高计算效率。
自底向上的方法是一种迭代的方法,它从较小的子问题开始,逐步解决大问题。我们首先计算最短的子序列,然后使用这些结果来计算更长的子序列。我们需要一个二维数组来存储每个子序列的最长公共子序列长度。在计算过程中,我们将数组填满,直到获得整个序列的最长公共子序列。
总体来说,这两种方法的思路类似,但具体实现方式略有不同。自顶向下的方法可以避免重复计算,但需要使用递归和数组来存储计算结果;自底向上的方法则可以避免递归和数组,但需要使用循环和二维数组来存储计算结果。
相关问题
c语言最长公共子序列自顶向下和自底向上代码
C语言中求解最长公共子序列可以使用动态规划算法,其中自顶向下和自底向上是两种不同的实现方式。
自顶向下的代码实现:
```
#include <stdio.h>
#include <string.h>
#define MAXLEN 100
int lcs(char *str1, char *str2, int m, int n, int memo[][MAXLEN]) {
if (m == 0 || n == 0) {
return 0;
}
if (memo[m-1] != -1) {
return memo[m-1][n-1];
}
if (str1[m-1] == str2[n-1]) {
memo[m-1][n-1] = 1 + lcs(str1, str2, m-1, n-1, memo);
} else {
memo[m-1][n-1] = (lcs(str1, str2, m, n-1, memo) > lcs(str1, str2, m-1, n, memo)) ? lcs(str1, str2, m, n-1, memo) : lcs(str1, str2, m-1, n, memo);
}
return memo[m-1][n-1];
}
int main() {
char str1[MAXLEN], str2[MAXLEN];
int m, n;
scanf("%s", str1);
scanf("%s", str2);
m = strlen(str1);
n = strlen(str2);
int memo[MAXLEN][MAXLEN];
memset(memo, -1, sizeof(memo));
printf("The length of the longest common subsequence is %d\n", lcs(str1, str2, m, n, memo));
return 0;
}
```
自底向上的代码实现:
```
#include <stdio.h>
#include <string.h>
#define MAXLEN 100
int lcs(char *str1, char *str2) {
int m = strlen(str1);
int n = strlen(str2);
int memo[MAXLEN][MAXLEN];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0 || j == 0) {
memo[i][j] = 0;
} else if (str1[i-1] == str2[j-1]) {
memo[i][j] = 1 + memo[i-1][j-1];
} else {
memo[i][j] = (memo[i][j-1] > memo[i-1][j]) ? memo[i][j-1] : memo[i-1][j];
}
}
}
return memo[m][n];
}
int main() {
char str1[MAXLEN], str2[MAXLEN];
scanf("%s", str1);
scanf("%s", str2);
printf("The length of the longest common subsequence is %d\n", lcs(str1, str2));
return 0;
}
```
使用动态规划算法实现最长公共子序列问题,输出最长公共子序列,c语言
以下是使用动态规划算法实现最长公共子序列问题,并输出最长公共子序列的C语言代码:
```c
#include <stdio.h>
#include <string.h>
#define MAXLEN 100
void LCS(char *str1, char *str2, int len1, int len2, int dp[MAXLEN][MAXLEN]) {
// 计算dp数组
for (int i = 0; i <= len1; i++) {
for (int j = 0; j <= len2; j++) {
if (i == 0 || j == 0) {
dp[i][j] = 0;
} else if (str1[i - 1] == str2[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 index = dp[len1][len2];
char lcs[index + 1];
lcs[index] = '\0';
int i = len1, j = len2;
while (i > 0 && j > 0) {
if (str1[i - 1] == str2[j - 1]) {
lcs[index - 1] = str1[i - 1];
i--;
j--;
index--;
} else if (dp[i - 1][j] > dp[i][j - 1]) {
i--;
} else {
j--;
}
}
// 输出最长公共子序列
printf("最长公共子序列为:%s\n", lcs);
}
int main() {
char str1[MAXLEN], str2[MAXLEN];
int dp[MAXLEN][MAXLEN] = {0};
printf("请输入第一个字符串:");
scanf("%s", str1);
printf("请输入第二个字符串:");
scanf("%s", str2);
int len1 = strlen(str1);
int len2 = strlen(str2);
LCS(str1, str2, len1, len2, dp);
return 0;
}
```
该代码在计算dp数组的同时,通过回溯的方式找到最长公共子序列。具体实现方式是,从dp数组的右下角开始,若`str1[i-1]`与`str2[j-1]`相等,则将该字符加入到最长公共子序列中,同时向左上角移动一格;否则,若`dp[i-1][j]`大于`dp[i][j-1]`,则向上移动一格,否则向左移动一格。最后输出最长公共子序列即可。
阅读全文