#include<iostream>
using namespace std;
#define NUM 100
int c[NUM][NUM];//c[i][j]用来记录序列Xi和Yj最长公共子序列的长度。其中Xi和Yj的下标都是从1开始。
int b[NUM][NUM];//辅助数组,b[i][j]记录c[i][j]的值是由哪个子问题的解得到的。
void LCSLength(char x[], int m, char y[], int n)
{
//当i=0||j=0 最长公共子序列为空,初始化为0.
for (int i = 0; i <= m; i++)c[i][0] = 0;
for (int i = 0; i <= n; i++)c[0][i] = 0;
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (x[i] == y[j])//两个序列的最后一个元素相同,则必选!相当于c[i-1][j-1]+1。
{
c[i][j] = c[i - 1][j - 1] + 1;
b[i][j] = 1;//来源于左上方。
}
//x[i]!=y[j]。
// 那么就相当于从x[i-1]和Y[j]找一个最长公共子序列,或者从x[i]和Y[j-1]找出一个最长公共子序列
// 二者选一个最大的。即c[i][j]=max(c[i-1][j],c[i][j-1])
else if (c[i - 1][j] >= c[i][j - 1])
{
c[i][j] = c[i - 1][j];
b[i][j] = 2;//来源于上方
}
else
{
c[i][j] = c[i][j - 1];
b[i][j] = 3;//来源于左方
}
}
}
}
void LCS(int i, int j, char x[])//只有b[i][j]=1时,才输出x[i]。
{
if (i == 0 || j == 0)
{
return;
}
if (b[i][j] == 1)//如果来源于左上方,说明Xi,Yj的最长公共子序列是由Xi-1,Yj-1的基础上加上Xi得到的。
{
LCS(i - 1, j - 1, x);//去递归左上角,并输出Xi。
cout << x[i] << " ";//因为是递归完才输出,所以是个正序。
}
else if (b[i][j] == 2)
{
LCS(i - 1, j, x);//去递归上方。
}
else
{
LCS(i, j - 1, x);//去递归左方。
}
}
int main()
{
char x[NUM];
char y[NUM];
cout << "请分别输入第一个数组和第二个数组的长度" << endl;
int m, n;
cin >> m >> n;
char x1;
cout << "请输入第一个数组的值" << endl;
for (int i = 1; i <= m; i++)
{
cin >> x1;
x[i] = x1;
}
cout << "请输入第二个数组的值" << endl;
for (int i = 1; i <= n; i++)
{
cin >> x1;
y[i] = x1;
}
cout << "最大公共子序列的长度是" << endl;
LCSLength(x, m, y, n);
cout << c[m][n] << endl;
cout << "最长公共子序列是:" << endl;
LCS(m, n, x);
}