1006 最长公共子序列Lcs
1 秒 / 131,072 KB / 基础题
问题
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。
比如两个串为:
abcicba
abdkscab
ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。输入
第1行:字符串A
第2行:字符串B
(A,B的长度 <= 1000)输出
输出最长的子序列,如果有多个,随意输出1个。
输入样例
abcicba
abdkscab输出样例
abca
解题时卡在没有想到好的方法输出路径(我用DFS一直错)。办法:记录路径。
如何记录路径:记录此状态的上一步,或者说记录当前是如何由上一步得出的。即:方向。
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
string a,b,ans;
const int Max_num=1e3+17;
int dp[Max_num][Max_num],book[Max_num][Max_num]; //book[][]记录方向
int main(){
cin>>a>>b;
int la=a.length(),lb=b.length(),tail=0;
for(int i=0;i<=la;++i) for(int j=0;j<lb;++j) dp[i][j]=0;
for(int i=1;i<=la;++i){
for(int j=1;j<=lb;++j){
if(a[i-1]==b[j-1]){ //分三个方向
dp[i][j]=dp[i-1][j-1]+1;
book[i][j]=0;
}
else if(dp[i-1][j]>dp[i][j-1]){
dp[i][j]=dp[i-1][j];
book[i][j]=1;
}
else{
dp[i][j]=dp[i][j-1];
book[i][j]=2;
}
}
}
bool flag=false;
for(int i=la;i>0;){
for(int j=lb;j>0;){
if(book[i][j]==0){
ans=a[i-1]+ans;
if(j-1>0&&i-1>0) j-=1,i-=1;
else{ flag=true;break;}
}
else if(book[i][j]==1){
if(i-1>0) --i;
else{ flag=true;break;}
}
else{
if(j-1>0)--j;
else{ flag=true;break;}
}
}
if(flag)break;
}
/*for(int i=0;i<=la;++i){
for(int j=0;j<=lb;++j)
printf("%d ",dp[i][j]);
printf("\n");
}
printf("\n");
for(int i=0;i<=la;++i){
for(int j=0;j<=lb;++j)
printf("%d ",book[i][j]);
printf("\n");
}*/
cout<<ans<<endl;
return 0;
}