动态规划之最长公共子序列
问题:
在序列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;
}
本文深入探讨了动态规划在解决最长公共子序列问题中的应用,通过实例详细讲解了算法的实现过程,包括如何构建状态转移方程以及如何从状态矩阵中回溯出最长公共子序列。
437





