最长公共子序列问题
Description
给定两个序列 X={x1,x2,…,xm} 和 Y={y1,y2,…,yn},找出X和Y的最长公共子序列。
Input
输入数据有多组,每组有两行 ,每行为一个长度不超过500的字符串(输入全是大写英文字母(A,Z)),表示序列X和Y。
Output
每组输出一行,表示所求得的最长公共子序列的长度,若不存在公共子序列,则输出0。
Sample
Input
ABCBDAB BDCABA
Output
4
解题思路:
最长公共子序列(Longest Common Sequence)
最长公共子序列问题不要求公共子序列部分连续,要求的是顺序相同的字符排列;最长公共子串问题要求的是一串相同的字符。
可参考:
1、最长公共子序列问题(动态规划) SDUT https://blog.csdn.net/weixin_44143702/article/details/89429776
2、https://www.cnblogs.com/wangkundentisy/p/9346376.html
#include <iostream> // cin cout
#include <cstring> //memset()
using namespace std;
int dp[505][505];///状态数组,可画出一个二维矩阵,代表dp[i][j]位置的最长公共子序列长度
string X, Y;
int LCS(int, int);///求解最长公共子序列的函数,两个参数为两个序列的长度
int main()
{
cin >> X >> Y;
int len_x = X.size();
int len_y = Y.size();
int common_len = LCS(len_x, len_y);///将函数返回的最长公共子序列长度保存
cout << common_len << endl;
return 0;
}
int LCS(int len_x, int len_y)
{///状态数组的长是从 0 到 len_x,宽是从 0 到 len_y
///初始化状态数组
memset(dp, 0, sizeof(dp));
for(int i = 0; i <= len_x; i++)
{///初始化状态数组的第一列
dp[i][0] = 0;
}
for(int j = 0; j <= len_y; j++)
{///初始化状态数组的第一行
dp[0][j] = 0;
}
///从左到右,从上到下填充状态数组的值,即dp[i][j]位置的最长公共子序列长度
for(int i = 1; i <= len_x; i++)
{///遍历X序列从第一位到最后一位,即控制第i行
for(int j = 1; j <= len_y; j++)
{///遍历Y序列从第一位到最后一位,即控制第j列
if(X[i - 1] == Y[j - 1])
{///如果两序列尾部相等,则当前位置的dp[i][j]等于左上角dp值+1
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else
{///如果两序列的末尾不相等,则取dp[i - 1][j]和dp[i][j - 1]的最大值
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[len_x][len_y];///返回序列X和Y整体的最长公共子序列的长度
}
参考:
1、动态规划经典——最长公共子序列问题 (LCS)和最长公共子串问题
https://www.cnblogs.com/wangkundentisy/p/9346376.html
2、最长公共子序列问题和动态规划