题目描述:
最长公共子序列问题:若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。
给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。
输入数据:输入包括多组测试数据。每组数据包括一行,给出两个长度不超过200的字符串,表示两个序列。两个字符串之间由若干个空格隔开。
输出要求:对每组输入数据,输出一行,给出两个序列的最大公共子序列的长度。
源程序:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX_LEN 1000
char str1[MAX_LEN];
char str2[MAX_LEN];
int maxLen[MAX_LEN][MAX_LEN];
int main()
{
while(scanf("%s%s",str1+1,str2+1)>0) //str1+1是指从str[1]开始存输入的字符
{
int length1=strlen(str1+1);
int length2=strlen(str2+1);
int tmp;
for(int i=0;i<=length1;i++)
maxLen[i][0]=0;
for(int i=0;i<=length2;i++)
maxLen[0][i]=0;
for(int i=1;i<=length1;i++)
{
for(int j=1;j<=length2;j++)
{
if(str1[i]==str2[j])
maxLen[i][j]=maxLen[i-1][j-1]+1;
else{
int len1=maxLen[i][j-1];
int len2=maxLen[i-1][j];
if(len1>len2)
maxLen[i][j]=len1;
else
maxLen[i][j]=len2;
}
}
}
printf("%d\n",maxLen[length1][length2]);
}
return 0;
}
下面这个还可以输出公共序列:
#include<iostream>
#include<cstdio>
using namespace std;
int c[100][100],b[100][100];
char x[100],y[100];
void LCSLength (int m, int n)
{
int i ,j;
for (i = 1; i <= m; i++) c[i][0] = 0;
for (i = 1; i <= n; i++) c[0][i] = 0;
for (i = 1; i <=m; i++)
for (j = 1; j <=n; j++)
{
if (x[i]==y[j])
{
c[i][j]=c[i-1][j-1]+1;
b[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)
{
if (i ==0 || j==0) return;
if (b[i][j]== 1)
{
LCS(i-1,j-1);
printf("%c",x[i]);
}
else if (b[i][j]== 2)
LCS(i-1,j);
else LCS(i,j-1);
}
int main()
{
int m,n;
cin>>m>>n;
for(int i=1;i<=m;i++)
cin>>x[i];
for(int i=1;i<=n;i++)
cin>>y[i];
cout<<endl;
LCSLength(m,n);
cout<<"最长公共子序列为:";
LCS(m,n);
return 0;
}