zoukankan      html  css  js  c++  java
  • 算法题9 动态规划之最长公共子序列&最长公共子串

    题目

      如果字符串1的所有字符按其在字符串中的顺序出现在另外一个字符串2中,则字符串1称之为字符串2的子序列。

      注意,并不要求子子序列(字符串1)的字符必须连续出现在字符串2中。

      请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子序列。

      例如:输入两个字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子序列,则输出它们的长度4,并打印任意一个子序列。

    分析

      本问题是典型的动态规划问题,子字符串的最优解为字符串提供了决策依据。有两个字符串str1和str2,设c[i,j]为子串str1[0-i]和str2[0-j]的最长公共子序列的长度,

      如果str1[i]=str2[j],则c[i,j]=c[i-1,j-1]+1;

      如果str1[i]!=str2[j],则c[i,j]要么等于str1[0,i-1]和str2[0,j]的最长公共子序列的长度,要么等于str1[0,i]和str2[0,j-1]的最长公共子序列的长度,取两者的最大值即是c[i,j]

      如图一个示例

            

      状态转移方程:

      c[0,j]=0;

      c[i,0]=0;

      c[i,j]=c[i-1,j-1]+1, 若str1[i]=str2[j];

      c[i,j]=max{c[i-1,j],c[i,j-1]}

    代码

     1 int Lcslen(char* stra,char* strb,int** c)
     2 {
     3     int len_a=strlen(stra);
     4     int len_b=strlen(strb);
     5 
     6     for(int i=1;i<=len_a;i++)
     7     {
     8         for(int j=1;j<=len_b;j++)
     9         {
    10             if(stra[i-1]==strb[j-1])
    11             {
    12                 c[i][j]=c[i-1][j-1]+1;
    13             }else
    14             {
    15                 c[i][j]=(c[i][j-1]>c[i-1][j])?c[i][j-1]:c[i-1][j];
    16             }
    17         }
    18     }
    19 
    20     return c[len_a][len_b];
    21 }
    22 
    23 void lcs(char* stra,char* strb)
    24 {
    25     if(stra==NULL||strb==NULL)
    26         return;
    27     int len_a=strlen(stra);
    28     int len_b=strlen(strb);
    29     int** c=new int*[len_a+1];
    30     for (int i=0;i<=len_a;i++)
    31     {
    32         c[i]=  new int[len_b+1]();
    33     }
    34 
    35     int k=Lcslen(stra,strb,c);
    36 
    37     char* lcs=new char[k];
    38 
    39     int i=len_a+1;
    40     int j=len_b+1;
    41     while(k>=0)
    42     {
    43         if(c[i][j]==c[i][j-1])
    44         {
    45             j--;
    46         }else if(c[i][j]==c[i-1][j])
    47         {
    48             i--;
    49         }else if(c[i][j]==c[i-1][j-1])
    50         {
    51             lcs[k--]=stra[i-1];
    52             i--;
    53             j--;
    54         }
    55     }
    56 
    57     for (int i=0;i<=len_a;i++)
    58     {
    59         delete[] c[i]; 
    60     }
    61     delete[] c;
    62 }

    动态规划之最长公共子串

      本题和上题的区别是子串要求是连续的。那么当str1[i]!=str2[j]的时候,前面的公共子串到此结束,c[i,j]重新等于0,开始寻找下一个公共子串。

      状态转移方程式变为:

      c[0,j]=0;

      c[i,0]=0;

      c[i,j]=c[i-1,j-1]+1, 若str1[i]==str2[j];

      c[i,j]=0, 若str1[i]!=str2[j]

      最大子串长度max_dis=max{c[i][j]}

    代码

     1 int ContinuousLCS(char* stra,char* strb)
     2 {
     3     if(stra==NULL||strb==NULL)
     4         return -1;
     5 
     6     int len_a=strlen(stra);
     7     int len_b=strlen(strb);
     8 
     9     //new space of int[][]
    10     int** c=new int*[len_a+1];
    11     for (int i=0;i<=len_a;i++)
    12     {
    13         c[i]=  new int[len_b+1]();
    14     }
    15 
    16     int max_dis=0,index=0;
    17     for(int i=1;i<=len_a;i++)
    18     {
    19         for(int j=1;j<=len_b;j++)
    20         {
    21             if(stra[i-1]==strb[j-1])
    22             {
    23                 c[i][j]=c[i-1][j-1]+1;
    24             }else
    25             {
    26                 c[i][j]=0;
    27             }
    28 
    29             if (max_dis<=c[i][j])
    30             {
    31                 max_dis=c[i][j];
    32                 index=i;
    33             }
    34         }
    35 
    36     }
    37 
    38     //output result
    39     for (int i=index-max_dis;i<index;i++)
    40     {
    41         cout<<stra[i]<<' ';
    42     }
    43     cout<<endl;
    44 
    45     //free
    46     for (int i=0;i<=len_a;i++)
    47     {
    48         delete[] c[i]; 
    49     }
    50     delete[] c;
    51 
    52     return max_dis;
    53 }
  • 相关阅读:
    2019.8.6原型链与继承
    2019.8.2闭包,作用域
    2019.8.1正则二
    2019.7.31正则
    2019.7.29二维数组
    2019.7.28关于数组和循环的八道题
    2019.7.27数组api
    DOM
    JavaScript数组5种去重方法
    JavaScript面向对象
  • 原文地址:https://www.cnblogs.com/wangzaizhen/p/5168909.html
Copyright © 2011-2022 走看看