最长公共子序列实现

参考《算法导论》译本(原书第二版)P208页

子序列的概念:一个给定序列的子序列就是该给定序列中去掉零个或者多个元素。

公共子序列:给定两个序列X和Y,如果Z既是X的一个子序列又是Y的一个子序列,则序列Z是X和Y的一个公共子序列。

最长公共子序列:X和Y的所有公共子序列中长度最长的公共子序列。

实现如下:

enum ValueFrom
{   
    TOPLEFT=0,   
    TOP,   
    LEFT   
};

string getResult(enum ValueFrom** valueFromArray,string x,int rows,int cols)  //此部分的时间复杂度为O(xLen+yLen),在递归的每个阶段,rows和cols至少有一个在减小  
{   
    string strRet;   
    if(rows==0||cols==0)   
    {   
        strRet.clear();   
        return strRet;   
    }

    if(valueFromArray[rows][cols]==TOPLEFT)  
    {   
        strRet.push_back(x.at(rows-1));   
        strRet.append(getResult(valueFromArray,x,rows-1,cols-1));   
    }   
    else if(valueFromArray[rows][cols]==TOP)   
        strRet.append(getResult(valueFromArray,x,rows-1,cols));   
    else    
        strRet.append(getResult(valueFromArray,x,rows,cols-1));

    return strRet;  
}

string getLongestCommonSubString(string x,string y)  
{   
    string strResult;   
    strResult.clear();

    int xLen=x.length();  
    int yLen=y.length();

    if(xLen==0||yLen==0)  
        return strResult;

    int** flagArray=new int*[xLen+1];  
    for(int i=0;i<xLen+1;i++)   
        flagArray[i]=new int[yLen+1];

    enum ValueFrom** valueFromArray=new enum ValueFrom*[xLen+1];  
    for(int i=0;i<xLen+1;i++)   
        valueFromArray[i]=new enum ValueFrom[yLen+1];

    //第一行第一列全部赋值为0  
    for(int i=1;i<xLen+1;i++) 
        flagArray[i][0]=0;   
    for(int j=0;j<yLen+1;j++)   
        flagArray[0][j]=0;

    for(int i=1;i<xLen+1;i++)   //此部分代码的时间复杂度为O(xLen*yLen)  
    {   
        char cx=x.at(i-1);   
        for(int j=1;j<yLen+1;j++)   
        {   
            char cy=y.at(j-1);   
            if(cx==cy)   
            {   
                flagArray[i][j]=flagArray[i-1][j-1]+1;   
                valueFromArray[i][j]=TOPLEFT;   
            }   
            else   
            {   
                if(flagArray[i-1][j]>=flagArray[i][j-1])   
                {   
                    flagArray[i][j]=flagArray[i-1][j];   
                    valueFromArray[i][j]=TOP;   
                }   
                else   
                {   
                    flagArray[i][j]=flagArray[i][j-1];   
                    valueFromArray[i][j]=LEFT;   
                }   
            }   
        }   
    }

    strResult=getResult(valueFromArray,x,xLen,yLen);  
    reverse(strResult.begin(),strResult.end());

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

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

    return strResult;  
}

实现步骤基本上与书中一致,没有什么好解释的,书中介绍的非常详细。  

所用测试代码为书中的两个DNA螺旋和解释算法的过程用到的例子:  

int _tmain(int argc, _TCHAR* argv[])  
{   
    string x="ACCGGTCGAGTGCGCGGAAGCCGGCCGAA";   
    string y="GTCGTTCGGAATGCCGTTGCTCTGTAAA";   
    string strRet=getLongestCommonSubString(x,y);   
    cout<<strRet<<endl;

    x="ABCBDAB";  
    y="BDCABA";   
    strRet=getLongestCommonSubString(x,y);   
    cout<<strRet<<endl;

    return 0;  
}

运行结果:image

整个算法的时间复杂度为O(xLen*yLen)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值