动态规划之最长公共子序列
问题:
在序列X={x1,x2,…,xm}与Y={y1,y2,…,yn}中查找长度最长的公共子序列,往往不是一个。例如:X={A,B,C,B,D,A,B},Y={B,D,C,A,B,A},则公共子序列有Z={B,C,B,A},Z1={B,D,A,B},Z2={B,C,A,B}
分析:
用c[i][j]记录序列Xi和Yi的最长公共子序列的长度。当i=0或者j=0时,Xi和Yi的最长公共子序列为空,所以c[i][j]=0。
其他情况:当xi=yi时,c[i][j]=c[i-1][j-1]+1。当xi不等于yi时,c[i][j]=max{c[i][j-1],c[i-1][j]}
代码:
#include<bits/stdc++.h>
using namespace std;
#define num 100
int c[num][num];//存放i,j之间最大公共子序列的长度
int b[num][num];//记录c[i][j]的值是哪得来的
void LCS(int m,int n,const char x[],const char y[]){
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[i]){
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;
}
}
}
}
由算法得到的数组b可用于快速构造序列X和Y的最长公共子序列
void LCS(int i,int j,char x[]){
if(i==1||j==0){return;}
if(b[i][j]==1){
LCS(i-1,j-1,x)
}
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];
int m,n;
cin>>m;
for(int i=1;i<=m;i++){
cin>>x[i];
}
cin>>n;
for(int i=1;i<=n;i++){
cin>>y[i];
}
cout<<"----------------"<<endl;
LCSLength(m,n,x,y);
cout<<c[m][n]<<endl;
LCS(m,n,x);
return 0;
}