动态规划法求两个序列的最长公共子序列

 

动态规划法求两个序列的最长公共子序列问题,MIT的perfessor讲的非常详细,根据他的算法的两种实现

注意,这里所指的最长公共子序列是可以不相邻的,与平常所说的最长公共子串(相邻的)不一样。

 

#include<stdio.h>
#include<iostream>
using namespace std;
#define max_num(x, y) (x)>(y)?(x):(y)

int c[100][100] = {-1};
int LCS(char a[], char b[], int i, int j)
{
   if (i == 0 || j == 0)
     c[i][j] = 0;
   else if (c[i][j] != -1)
   {
       if (a[i] == b[j])
       {
           c[i][j] = LCS(a, b, i-1, j-1) + 1;
       } 
       else
       {
          int L1 = LCS(a, b, i-1, j);
          int L2 = LCS(a, b, i, j-1);
          c[i][j] = max_num(L1, L2);
       }
   }
   return c[i][j];
}
int main(int n, char * argv[])
{
   char a[] = {'B', 'D', 'C', 'A', 'B', 'A'};
   char b[] = {'A', 'B', 'C', 'B', 'D', 'A', 'B'};
   int m = sizeof(a)/sizeof(char);
   int n = sizeof(b)/sizeof(char);
   int len_lcs = LCS(a, b, m, n);
   cout<<"max LCS is: "<<len_lcs<<endl;
   return 1;
}
 
 
 
//above algorithm can only count the length, below function can get the LCS sequence

#include<stdio.h> #include<iostream> using namespace std;

int c[100][100]; int flag[100][100] = {-1};  //it saves the character int LCS(char a[], char b[], int m, int n) {    int i, j;

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

   //a[0...m-1], b[0...n-1], c[0,..., m][0,...,n]    for (i = 1; i <= m; i++)     for (j = 1; j <= n; j++)     {         if (a[i-1] == b[j-1])         {             c[i][j] = c[i-1][j-1] + 1;             flag[i][j] = 1;         }         else if (c[i-1][j] >= c[i][j-1])         {             c[i][j] = c[i-1][j];             flag[i][j] = 2;         }         else         {             c[i][j] = c[i][j-1];             flag[i][j] = 3;         }     }     return c[m][n]; }

/************non-recursion print LCS*****************/ void printLCS(int flag[100][100], char a[], int m, int n) {     int i, j, k;     char res[100];     k = 0;     i = m;     j = n;     while (i > 0 && j > 0)     {        switch(flag[i][j])        {                  case 1:             {                 res[k++] = a[i-1];                 i--;                 j--;                 break;             }           case 2:             {                 i--;                 break;             }           case 3:             {                j--;                break;             }        }     }

    for (i = k - 1; i >= 0; i--)         cout<<res[i];     cout<<endl; } /************recursion print LCS***************** void printLCS(int flag[][100], char a[], int i, int j) {     if(i == 0 || j == 0)         return;     if(flag[i][j] == 1)     {         printLCS(flag, a, i-1, j-1);         printf("%c ", a[i-1]);     }     else if(flag[i][j] == 2)         printLCS(flag, a, i-1, j);     else         printLCS(flag, a, i, j-1); } *****************************************/ int main(int argc, char * argv[]) {    char a[] = {'B', 'D', 'C', 'A', 'B', 'A'};    char b[] = {'A', 'B', 'C', 'B', 'D', 'A', 'B'};    int m = sizeof(a)/sizeof(char);    int n = sizeof(b)/sizeof(char);    int len_lcs = LCS(a, b, m, n);    cout<<"max LCS is: "<<len_lcs<<endl;    printLCS(flag, a, m, n);    return 1; }


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值