算法老师的作业,一道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 4A 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;
}