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 }
  • 相关阅读:
    XML(学习笔记)
    css样式学习笔记
    Request(对象)
    sql一些错误修改的总结
    转载(如何学习C#)
    sql server(学习笔记2 W3Cschool)
    sql sqrver(学习笔记1 W3Cschool)
    关于 flutter开发碰到的各种问题,有的已经解决有的一直没解决或者用其他方法替代
    关于 Flutter IOS build It appears that your application still contains the default signing identifier.
    关于 flutter本地化问题 The getter 'pasteButtonLabel' was called on null
  • 原文地址:https://www.cnblogs.com/wangzaizhen/p/5168909.html
Copyright © 2011-2022 走看看