算法老师的作业,一道dp基础题,给你两个序列,问你最长公共子序列是什么,比如:(a,b)是(a,c,d,b)的子序列。注意不是最长公共子串,这里的子序列可以不连续。
两个for循环就出来了,每一个dp[i][j]可以从dp[i-1][j-1]、dp[i-1][j]、dp[i][j-1]三种情况更新过来,取个最大的,然后把路径用123存下来,最后再顺着路径找然后逆序输出就行。
sample input:
7 4
A B C B D A B
B C D B
7 6
A B C B D A B
B D C A B A
8 4
A B C D E F G H
D C B A
#include <iostream> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string> #include <string.h> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <stack> using namespace std; typedef long long LL; const int INF=0x7fffffff; const int MAX_N=1009; char X[MAX_N],Y[MAX_N]; int m,n,ct; int dp[MAX_N][MAX_N]; int b[MAX_N][MAX_N]; char ans[MAX_N]; void solve(){ for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ if(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]){ dp[i][j]=dp[i-1][j]; b[i][j]=2; } else{ dp[i][j]=dp[i][j-1]; b[i][j]=3; } } } } void go_back(int x,int y){ if(x==0||y==0)return; if(b[x][y]==1){ ans[++ct]=X[x]; return go_back(x-1,y-1); } if(b[x][y]==2){ return go_back(x-1,y); } if(b[x][y]==3){ return go_back(x,y-1); } } int main(){ printf("输入x和y的长度:\n"); while(scanf("%d%d",&m,&n)!=EOF){ memset(dp,0,sizeof(dp)); memset(b,0,sizeof(b)); printf("输入序列X:\n"); for(int i=1;i<=m;i++){ scanf(" %c",&X[i]); } // getchar(); printf("输入序列Y:\n"); for(int i=1;i<=n;i++){ scanf(" %c",&Y[i]); } solve(); printf("最长子序列长度为:%d\n",dp[m][n]); ct=0; go_back(m,n); printf("最长子序列之一为:\n"); for(int i=ct;i>=1;i--){ printf("%c ",ans[i]); } printf("\n\n输入x和y的长度:\n"); } return 0; }
时间: 2024-10-20 17:29:12