动态规划之最长公共子序列(lcs)

        最长公共子序列的定义是,一个数列z分别是已知数列的子序列(子序列不一定是连续序列,是在该序列中删去若干元素后得到的序列),且是所有符合此条件序列中最长的,则z成为最长公共子序列lcs(Longest Common Subsequences)。有些地方则说公共子串就是要求连续的子序列,有些地方则不是,这里要注意区分。下面是完整实现代码。

#include <iostream>
using namespace std;
void LCS_Length(char *x,char *y,int **b,int m,int n)
{
 //c[i][j]表示x[i-1],y[j-1]之前公共子序列的长度,i表示x数组前进,j表示y数组前进
 //不用c[i][j]表示x[i],y[j]之前公共子序列的长度是因为需要使用c[0][0]来表示没有公共子序列,
 //即c[0][0]恒等于0,因此c数组最大下标为c[m+1][n+1]
 int **c;
 c=new int*[m+1];
 for( int i=0;i<m+1;i++)
  c[i]=new int[n+1];

 for(int i=0;i<m+1;i++)
  c[i][0]=0;
 for(int i=0;i<n+1;i++)
  c[0][i]=0;

 for(int i=1;i<=m;i++)
 {
  for(int j=1;j<=n;j++)
  {
   if(x[i-1]==y[j-1])//找到一个公共“字符”
   {
    c[i][j]=c[i-1][j-1]+1;//公共子序列的长度在原来的基础上加1
    b[i][j]=0;//做一个辅助标志,表示要达到目前的长度,x,y数组均需“前进”一步
        //即x[i-1],y[j-1]都要作出贡献
   }
   //当前字符不相同,且x数组后退一步(即c[i-1][j])比y数组后退一步(即c[i][j-1])
   //所得到的公共子序列的长度要长,隐含的意思是当前最长公共子序列可以不需要x[i-1]
   else if(c[i-1][j]>=c[i][j-1])
   {
    c[i][j]=c[i-1][j];//当前最长公共子序列可以不需要x[i-1]
    b[i][j]=-1;
   }
   //和上面分析类似
   else
   {
    c[i][j]=c[i][j-1];//当前最长公共子序列可以不需要y[j-1]
    b[i][j]=1;
   }
  }
 }
 for(int i=0;i<m+1;i++)  
 {  
  delete c[i];
  c[i]=NULL;
 }  
 delete []c;  
 c=NULL; 
}

//打印结果
void Print_LCS(int **b,char *x,int i,int j)
{
 if(i==0||j==0)
  return ;
 if(b[i][j]==0)
 {
  Print_LCS(b,x,i-1,j-1);
  cout<<x[i-1];
 }
 else if(b[i][j]==-1)
  Print_LCS(b,x,i-1,j);
 else
  Print_LCS(b,x,i,j-1);
}


int _tmain(int argc, _TCHAR* argv[])
{
 char x[]="ADAB";
 char y[]="ADCA";
 int m=strlen(x);
 int n=strlen(y);

 int **b;
 b=new int*[m+1];
 for( int i=0;i<m+1;i++)
  b[i]=new int[n+1];

 LCS_Length(x,y,b,m,n);
 Print_LCS(b,x,m,n);

 for(int i=0;i<m+1;i++)  
 {  
  delete b[i];
  b[i]=NULL;
 }  
 delete []b;  
 b=NULL; 

 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值