给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。比如两个串为:
abcicba
abdkscab
ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。
输入
第1行:字符串A
第2行:字符串B
(A,B的长度 <= 1000)
输出
输出最长的子序列,如果有多个,随意输出1个。
输入样例
abcicba
abdkscab
输出样例
abca
dp[i][j]:i表示A j表示B 的每一个字符
dp表示I位Aj位B的公共子串的最长长度
若相同:dp[i][j]=dp[i-1][j-1]+1;
否则:dp[i][j]-max(dp[i-1][j],dp[i][j-1])
因为要输出字串,就用一个direct记录转移的方向
#include<bits/stdc++.h>
using namespace std;
char a[1010],b[1010];
int Mlen[1010][1010],direc[1010][1010];//0左 1左上 2上
void print(int x,int y)
{
if(x<0||y<0) return;
if(direc[x][y]==2)
print(x-1,y);
else if(direc[x][y]==0)
print(x,y-1);
else
{
print(x-1,y-1);
cout<<a[x];
}
}
int main()
{
cin>>a>>b;
int lena=strlen(a),lenb=strlen(b);
memset(direc,0,sizeof(direc));
for(int i=0;i<lena;i++)
for(int j=0;j<lenb;j++)
{
//0-1 越界 特判
if((i+j)==0)
{
if(a[i]==b[j])
{Mlen[i][j]=1;direc[i][j]=1;}
else Mlen[i][j]=0;
}
if(i==0||j==0)
{
if(a[i]==b[j])
{
Mlen[i][j]=1;direc[i][j]=1;
}
else
{
Mlen[i][j]=(i==0?Mlen[i][j-1]:Mlen[i-1][j]);
direc[i][j]=(j==0?2:0);
} continue;
}
//dp
if(a[i]==b[j])
{
Mlen[i][j]=Mlen[i-1][j-1]+1;
direc[i][j]=1;
}
else
{
if(Mlen[i-1][j]>=Mlen[i][j-1])
{
Mlen[i][j]=Mlen[i-1][j];
direc[i][j]=2;
}
else
{
Mlen[i][j]=Mlen[i][j-1];
}
}
}
print(lena-1,lenb-1);
cout<<endl;
/*for(int i=0;i<lena;i++)
{
for(int j=0;j<lenb;j++)
cout<<Mlen[i][j]<<" ";
cout<<endl;
}*/
return 0;
}
来源:https://blog.csdn.net/weixin_43540515/article/details/100086080