题目描述:从a,b俩数组中找出共有的最长子序列,如a={1,2,3,5,6,4,8},b={1,1,2,5,5,3,5,7,6,},其最长公共子序列为{1,2,3,5,6}.
解决方法:动态规划,寻找子问题,可以发现,当前的最长子序列一定等于上一次的加一,否则,就等于上一次的。
即:c[i][j]=0; 当i==0或j==0时
c[i][j]=c[i-1][j-1]+1. 当a[i]=b[j]时
c[i][j]=c[i-1][j]. 当c[i-1][j]>c[i][j-1]时
c[i][j]=c[i][j-1]. 当c[i][j-1]>c[i][j-1]时
i和j分别表示数组a中前i个和数组b中前j个的最长公共子序列.
代码如下:
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 using namespace std; 5 int longque(int m,int n,int *a,int *b,int **c,int **flag) 6 { 7 for(int i=0;i<=n;i++) //初始化0行0列 8 c[i][0]=0; 9 for(int i=0;i<=m;i++) 10 c[0][i]=0; 11 12 int max1=0; 13 for(int i=1;i<=n;i++) 14 { 15 for(int j=1;j<=m;j++) 16 { 17 if(a[i]==b[j]) //相等时+1,标标记为1 18 { 19 c[i][j]=c[i-1][j-1]+1;flag[i][j]=1; 20 } 21 else if(c[i-1][j]>c[i][j-1]){ //不相等时,取大的并标记 22 c[i][j]=c[i-1][j]; flag[i][j]=2; 23 }else{ 24 c[i][j]=c[i][j-1]; flag[i][j]=3; 25 } 26 max1=max(max1,c[i][j]); 27 } 28 29 } 30 31 return max1; 32 } 33 void LCS(int i,int j,int **flag,int *a) 34 { 35 if(i==0||j==0)return; 36 if(flag[i][j]==1) //相等时,为公共最长子序列输出 37 { 38 LCS(i-1,j-1,flag,a);cout<<a[i]<<" "; 39 }else if(flag[i][j]==2) 40 { 41 LCS(i-1,j,flag,a); 42 }else 43 { 44 LCS(i,j-1,flag,a); 45 } 46 } 47 int main() 48 { 49 int n,m; 50 cout<<"俩数组长度分别为"<<endl; 51 cin>>n>>m; 52 int a[n+1]; 53 int b[m+1]; 54 cout<<"输入"<<n<<"个数"<<endl; 55 for(int i=1;i<=n;i++) 56 { 57 cin>>a[i]; 58 } 59 cout<<"输入"<<m<<"个数"<<endl; 60 for(int i=1;i<=m;i++) 61 { 62 cin>>b[i]; 63 } 64 65 int *c[n+1],*flag[n+1]; //数组c[i][j],标记数组flag[i][j]. 66 for(int i=0;i<n+1;i++) 67 { 68 c[i]=(int *)malloc((m+1)*sizeof(int)); 69 flag[i]=(int *)malloc((m+1)*sizeof(int)); 70 } 71 cout<<"最长公共子序列为"<<endl; 72 cout<<longque(m,n,a,b,c,flag)<<endl; //求最长公共子序列长度 73 LCS(n,m,flag,a); //打印序列 74 75 }
时间: 2024-10-23 19:42:44