注意:
1、字符串X和Y的下标范围是0~m-1和0~n-1,如果不在输入时做特殊处理的话(即:gets(X)),在LCSLength中判断条件就要改成x[i-1]==y[j-1],LCS中 cout<<x[i-1];不改的话,也能输出正确的长度主要是因为X,Y都是全局变量,默认初始化后XY里面全是0,所以X[m]==Y[n],事实就是如果你输入abcd abc,程序实际算了bcd0 bc0
如果在输入时做特殊处理(即:gets(X+1)),在LCSLength中判断条件就可以成x[i]==y[j],LCS中 cout<<x[i];
2、 for(i=0;i<=m;i++) dp[i][0]=0; 此处i要从0开始
3、 LCS(m,n,X,b); 此处要写X,即输出X中的共同字符,否则可能输不出结果
#include<iostream>
#include<cstring>
using namespace std;
const int N=100;
char X[N],Y[N];
int dp[N][N];//dp[i][j]记录最长公共子序列的长度
int b[N][N];//b[i][j]记录dp[i][j]由哪一个子问题解得
int LCSLength(char *x,char *y,int m,int n)//求最长公共子序列的长度
{
int i,j;
for(i=0;i<=m;i++) dp[i][0]=0;//Y字符串长度为0时,最长公共子序列的长度为0
for(j=0;j<=n;j++) dp[0][j]=0;//X字符串长度为0时,最长公共子序列的长度为0
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(x[i]==y[j])//X字符串中i位置的字符==Y字符串中j位置的字符
{
dp[i][j]=dp[i-1][j-1]+1;
b[i][j]=1;
}
else if(dp[i-1][j]>=dp[i][j-1])//若不考虑b[][],可简写为dp[i][j]=max(dp[i-1][j],dp[i][j-1])
{
dp[i][j]=dp[i-1][j];
b[i][j]=2;
}
else
{
dp[i][j]=dp[i][j-1];
b[i][j]=3;
}
}
return dp[m][n];
}
int LCS(int i,int j,char *x,int (*b)[N])//构造最长公共子序列
{
if(i==0||j==0) return 0;
if(b[i][j]==1)
{
LCS(i-1,j-1,x,b);
cout<<x[i];
}
else if(b[i][j]==2)
{
LCS(i-1,j,x,b);
}
else
{
LCS(i,j-1,x,b);
}
}
int main()
{
gets(X+1);//从下标为1开始读入
gets(Y+1);
int m=strlen(X+1);//由于读入时下标从1开始,因此读取长度也从+1开始
int n=strlen(Y+1);
cout<<"X和Y最长公共子序列的长度:"<<LCSLength(X,Y,m,n)<<endl;
cout<<"X和Y最长公共子序列为:";
LCS(m,n,X,b);
return 0;
}