1006 最长公共子序列Lcs

给出两个字符串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;
}
上一篇:Codeforces Round #611 (Div. 3)


下一篇:LeetCode: 14 最长公共前缀