C语言动态规划法解决最长公共子序列问题:思路分析与代码详解
C语言动态规划法解决最长公共子序列问题:思路分析与代码详解
问题分析思路:
最长公共子序列问题是指给定两个序列,找出它们最长的公共子序列的长度。子序列是指从原序列中删除0个或多个元素而不改变其余元素的相对顺序得到的序列。
动态规划是解决最长公共子序列问题的常用方法。首先定义一个二维数组dp用来记录最长公共子序列的长度,其中dp[i][j]表示序列1的前i个元素与序列2的前j个元素的最长公共子序列长度。然后根据递推关系,我们可以得到dp[i][j]的值。
具体的递推关系如下:
- 当序列1的第i个元素等于序列2的第j个元素时,即s1[i-1] == s2[j-1],dp[i][j] = dp[i-1][j-1] + 1,表示当前的最长公共子序列长度等于前一个最长公共子序列长度加1。
- 当序列1的第i个元素不等于序列2的第j个元素时,即s1[i-1] != s2[j-1],dp[i][j] = max(dp[i-1][j], dp[i][j-1]),表示当前的最长公共子序列长度等于序列1的前i-1个元素与序列2的前j个元素的最长公共子序列长度和序列1的前i个元素与序列2的前j-1个元素的最长公共子序列长度中的较大值。
代码如下所示:
#include <stdio.h>
#include <string.h>
int max(int a, int b) {
return (a > b) ? a : b;
}
int longestCommonSubsequence(char* s1, char* s2) {
int m = strlen(s1);
int n = strlen(s2);
int dp[m+1][n+1]; // 定义dp数组
// 初始化边界条件
for (int i = 0; i <= m; i++) {
dp[i][0] = 0;
}
for (int j = 0; j <= n; j++) {
dp[0][j] = 0;
}
// 计算dp数组的值
for (int i = 1; i <= m; i++) {
for (int 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]);
}
}
}
return dp[m][n]; // 返回最长公共子序列的长度
}
int main() {
char s1[] = "abcde";
char s2[] = "ace";
int result = longestCommonSubsequence(s1, s2);
printf("The length of the longest common subsequence is: %d", result);
return 0;
}
注释解析:
- 定义了一个max函数用来返回两个数中的较大值。
- 定义了longestCommonSubsequence函数,接受两个字符串s1和s2作为参数,返回最长公共子序列的长度。
- 使用strlen函数得到字符串s1和s2的长度,分别赋值给变量m和n。
- 定义一个二维数组dp,大小为(m+1) * (n+1),其中dp[i][j]表示序列1的前i个元素与序列2的前j个元素的最长公共子序列长度。
- 初始化边界条件,即当i等于0或j等于0时,dp[i][j]的值都为0,表示空序列与任意序列的最长公共子序列长度都为0。
- 使用两层循环计算dp数组的值,根据递推关系更新dp[i][j]的值。
- 返回dp[m][n],即最长公共子序列的长度。
- 在main函数中,定义了两个测试字符串s1和s2,调用longestCommonSubsequence函数计算最长公共子序列的长度,并打印结果。
总结: 本文详细介绍了使用动态规划算法解决最长公共子序列问题的思路,并提供完整的C语言代码示例,包含清晰的代码注释,帮助您理解动态规划思想和实现细节。希望本文能对您学习和应用动态规划算法有所帮助。
原文地址: https://www.cveoy.top/t/topic/pdnz 著作权归作者所有。请勿转载和采集!