Longest Common Subsequence
- 和最长公共子串的区别: 最长公共子串要求是连续的,公共子序列不要求,但是顺序要对。比如:abcde 和 abefd 的最长公共子串是 ab,最长公共子序列是 abd。它们都不一定是唯一的,但长度是唯一的。
- 核心思想:
- 如果两个序列的最后一个元素相同,那么LCS的最后一个元素一定是它;如果两个序列的最后一个元素不同,那么LCS的最后一个元素可能为二者之一,也可能都不是,所以其中一个序列的最后那个元素就是可有可无的(不影响LCS),比如 “hello” “heroine” 的LCS 和 “hello” “heroin” LCS完全一样。但是当时无法知道哪个是没用的。
- 所以求解 “hello” “hero” 的LCS 可以化解成 --> 求解 “hell” “her” 的LCS + ‘o’。 “hell” “her” 的LCS 又可以化解成 -->求解 “hel”“her” 和 “hell”“he”中那个最终长度较长序列的LCS。
- 实现方法:
- 序列从空开始逐渐增加,自底向上求解
- 要先求出最长子序列的长度,再推出序列
- 只要理解下面的递推公式或者表格就可以写代码求出LCS长度啦
- 再理解倒推出LCS的方法就可以写代码求出LCS啦
- 递归,自顶向下求解(本文章暂时没写...以后补上)
- 序列从空开始逐渐增加,自底向上求解
LCS长度的递推公式
LCS长度的二维表格
一行一行填,原则:LCS长度的递推公式
倒推出LCS
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
string a, b, lcs;
cin >> a;
cin >> b;
int len_a = a.length();
int len_b = b.length();
int dp[len_a + 1][len_b + 1];
memset(dp, 0, sizeof(dp));
// 求长度
for (int i = 0; i < len_a; i++)
{
for (int j = 0; j < len_b; j++)
{
if (a[i] == b[j])
{
dp[i + 1][j + 1] = dp[i][j] + 1;
}
else if (dp[i][j + 1] > dp[i + 1][j])
dp[i + 1][j + 1] = dp[i][j + 1];
else
dp[i + 1][j + 1] = dp[i + 1][j];
}
}
cout << "the length of LCS is " << dp[len_a][len_b] << endl;
// 求LCS
for (int i = len_a - 1, j = len_b - 1; i >= 0;)
{
if (a[i] == b[j])
{
lcs = a[i] + lcs;
i--;
j--;
}
else if (dp[i][j + 1] > dp[i + 1][j])
i--;
else
j--;
}
cout << "LCS = " << lcs << endl;
}
不知道有没有讲清楚😅,欢迎交流指正!😊