zoukankan      html  css  js  c++  java
  • 最长公共子串

    问题描述:

         求解两个字符串的最长公共子串

    参考资料:

    1、http://blog.csdn.net/yysdsyl/article/details/4226630

    2、http://www.cnblogs.com/huangxincheng/archive/2012/11/11/2764625.html

    问题解决:

        使用动态规划,考虑如何将原问题转换为子问题,假设字符串X形如x1 x2 x3 x4....xm

    字符串Y形如y1 y2 y3...yn,考虑X和Y的最长公共子串:

       若x1=y1,则原问题可以转化为求解x2 x3 x4...xm与y2 y3 y4...yn的最长公共子串

        若x1!=y1,则原问题可以转换为求解x2 x3 x4...xm 与 y1 y2 y3 y4...yn 或者 x1 x2 x3 x4...xm  与y2 y3 y4...yn 的最长公共子串

        现在使用二维数组c[i][j]表示字符串X[i]的前i个元素与Y[j]的前j个元素的最长公共子串长度,则有:

    clipboard

    以字符串X="ABCBDAB"  和字符串Y="BDCABA" 为例子,生成的c[i][j]如下所示:

    clipboard[1]

            回溯输出字符串,使用一个二维数组b[i][j]记录c[i][j]通过哪一个子问题求得,如下:

    clipboard[2]

    也就是,当b[i][j]=0相当于如上图中的  左上箭头,b[i][j]=1 为如上图的向上箭头

    b[i][j]=-1为如上图的向左箭头。

    代码文件:

    /**
    *    求解最长公共子序列
    *    满足动态规划的条件,使用动态规划的思想求解。
    *        考虑最长公共子序列问题如何分解成子问题,设X=“x0,x1,…,xm-1”,Y=“y0,y1,…,ym-1”,
    *    并Z=“z0,z1,…,zk-1”为它们的最长公共子序列。不难证明有以下性质:
    *
    *(1) 如果xm-1=yn-1,则zk-1=xm-1=yn-1,且“z0,z1,…,zk-2”是“x0,x1,…,xm-2”和“y0,y1,…,yn-2”的一个最长公共子序列;
    *
    *(2) 如果xm-1!=yn-1,则若zk-1!=xm-1,蕴涵“z0,z1,…,zk-1”是“x0,x1,…,xm-2”和“y0,y1,…,yn-1”的一个最长公共子序列;
    *
    *(3) 如果xm-1!=yn-1,则若zk-1!=yn-1,蕴涵“z0,z1,…,zk-1”是“x0,x1,…,xm-1”和“y0,y1,…,yn-2”的一个最长公共子序列。
    *    
    *
    *
    *   这样,在找X和Y的公共子序列时,
    *    如有xm-1=yn-1,则进一步解决一个子问题,找“x0,x1,…,xm-2”和“y0,y1,…,ym-2”的一个最长公共子序列;
    *    如果xm-1!=yn-1,则要解决两个子问题,找出“x0,x1,…,xm-2”和“y0,y1,…,yn-1”的一个最长公共子序列和
    * 找出“x0,x1,…,xm-1”和“y0,y1,…,yn-2”的一个最长公共子序列,再取两者中较长者作为X和Y的最长公共子序列。
    *
    *     引进一个二维数组c[][],用c[i][j]记录X前i个子串与Y前j个子串的LCS 的长度,b[i][j]记录c[i][j]是通过哪一个子问题的值求得的,
    *  以决定搜索的方向。
    *     我们是自底向上进行递推计算,那么在计算c[i,j]之前,c[i-1][j-1],c[i-1][j]与c[i][j-1]均已计算出来。
    *  此时我们根据X[i] = Y[j]还是X[i] != Y[j],就可以计算出c[i][j]。
    *
    */
    #include <iostream>
    using namespace std;
    
    void LCSLength(char* x,char* y,int m,int n,int** c,int** y)
    {
        for (int i=0;i<=m;i++)
        {
            c[i][0]=0;
        }
    
        for (int j=1;j<=n;j++)
        {
            c[0][j]=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;
                    b[i][j]=0;
                }
                else if (c[i][j-1]>c[i-1][j])
                {
                    c[i][j]=c[i][j-1];
                    b[i][j]=-1;
                }
                else
                {
                    c[i][j]=c[i-1][j];
                    b[i][j]=1;
                }
            }
        }
    
        //输出X[i]和Y[j]的最长公共子串的长度c[i][j]
        for (int i=0;i<=m;i++)
        {
            for (int j=0;j<=n;j++)
            {
                cout<<c[i][j]<<"	";
            }
            cout<<endl;
        }
        cout<<endl;
    }
    
    
    //回溯,输出最长公共子串
    void PrintLCS(char* x,int** c,int** b,int m,int n)
    {
        if (m==0||n==0)
        {
            return ;
        }
    
        if (b[m][n]==0)
        {
            PrintLCS(x,c,b,m-1,n-1);
            cout<<x[m-1];
        }
        else if (b[m][n]==1)
        {
            PrintLCS(x,c,b,m-1,n);
        }
        else
        {
            PrintLCS(x,c,b,m,n-1);
        }
    }
    
    int main()
    {
        char* x="ABCBDAB";
        char* y="BDCABA";
    
        int m=7;
        int n=6;
    
        int **c=new int*[m+1];
        for (int i=0;i<=m;i++)
        {
            c[i]=new int[n+1];
        }
    
        //new 二维数组
        int **b=new int*[m+1];
        for (int i=0;i<=m;i++)
        {
            b[i]=new int[n+1];
        }
    
        LCSLength(x,y,m,n,c,b);
    
        PrintLCS(x,c,b,m,n);
        cout<<endl;
    
        for (int i=0;i<=m;i++)
        {
            delete []c[i];
        }
    
        for (int i=0;i<=m;i++)
        {
            delete []b[i];
        }
    }
  • 相关阅读:
    深度学习分类网络的发展历史
    杨辉三角
    【了解】贝塞尔曲线
    win10桌面点击事件蓝色边框处理
    try{}catch的隐藏(如何优雅的实现异常块)
    switch的一些思考(seitch与ifelse的区别)
    好看的控制台日志线
    Serializable和Externalizabl的异同
    java排序方式对比
    如何初始化Map,java
  • 原文地址:https://www.cnblogs.com/luosongchao/p/3553197.html
Copyright © 2011-2022 走看看