最长公共子序列问题动态规划c++
时间: 2023-06-10 21:07:24 浏览: 157
基于C++实现的通过动态规划查找最长公共子序列计算字符串之间相似度.zip
最长公共子序列问题是一种经典的动态规划问题,它可以用来求两个字符串之间的最长公共子序列。以下是该问题的动态规划解法。
我们令 $dp[i][j]$ 表示字符串 $s1$ 的前 $i$ 个字符和字符串 $s2$ 的前 $j$ 个字符的最长公共子序列长度,那么状态转移方程为:
$$
dp[i][j] =
\begin{cases}
0, & i=0 \text{ 或 } j=0 \\
dp[i-1][j-1]+1, & s1[i]=s2[j] \\
\max(dp[i][j-1], dp[i-1][j]), & s1[i] \neq s2[j]
\end{cases}
$$
其中,当 $s1[i]=s2[j]$ 时,$dp[i][j]$ 等于 $s1$ 的前 $i-1$ 个字符和 $s2$ 的前 $j-1$ 个字符的最长公共子序列长度 $dp[i-1][j-1]$ 加上当前字符相同的贡献 $1$。
当 $s1[i] \neq s2[j]$ 时,$dp[i][j]$ 取 $s1$ 的前 $i$ 个字符和 $s2$ 的前 $j-1$ 个字符的最长公共子序列长度 $dp[i][j-1]$ 和 $s1$ 的前 $i-1$ 个字符和 $s2$ 的前 $j$ 个字符的最长公共子序列长度 $dp[i-1][j]$ 的较大值。
最终结果即为 $dp[n][m]$,其中 $n$ 和 $m$ 分别为字符串 $s1$ 和 $s2$ 的长度。
以下是该问题的 C 代码实现:
```c
#include <stdio.h>
#include <string.h>
#define MAX_N 1000
int dp[MAX_N + 1][MAX_N + 1];
int lcs(char *s1, char *s2) {
int n = strlen(s1), m = strlen(s2);
for (int i = 0; i <= n; ++i) dp[i][0] = 0;
for (int j = 0; j <= m; ++j) dp[0][j] = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (s1[i - 1] == s2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = dp[i][j - 1] > dp[i - 1][j] ? dp[i][j - 1] : dp[i - 1][j];
}
}
}
return dp[n][m];
}
int main() {
char s1[MAX_N + 1], s2[MAX_N + 1];
scanf("%s%s", s1, s2);
printf("%d\n", lcs(s1, s2));
return 0;
}
```
阅读全文