最长公共子序列的C++实现---附二维指针的使用方法

想了挺久到底第一篇在这儿的博客写什么好,刚好这两天又一次看到动态规划的LCS算法觉得还是有点意思的,就拿来写了写,第一篇博客就发它吧。

#include<iostream>
#include<iomanip>
using namespace std;
//tag标志,0为左斜上,1取左,2取上;count为最长公共子序列计数
//计算最长公共子序列长度
void LCS_Length(char *X, char *Y, int *count[],int *tag[],int length_X, int length_Y)
{
    //第一排第一列全部是0
    for (int i = 0; i < length_X+1; i++)
    {
        count[i][0] = 0;
    }
    for (int i = 0; i < length_Y+1; i++)
    {
        count[0][i] = 0;
    }

    for (int i = 1; i <= length_X; i++)
    {
        for (int j = 1; j <= length_Y; j++)
        {
            if (X[i-1] == Y[j - 1])
            {
                count[i][j] = count[i-1][j-1]+1;
                tag[i][j] = 0;
            }
            //否则取较大的值
            else if(count[i-1][j] > count[i][j-1])
            {
                count[i][j] = count[i-1][j];
                tag[i][j] = 1;
            }
            else
            {
                count[i][j] = count[i][j-1];
                tag[i][j] = 2;
            }
        }
    }
}
//打印最长公共子序列元素
void Print_LCS(int *tag[],char *X,int Length_X, int Length_Y)
{
    if (Length_X == 0 || Length_Y == 0)
    {
        return ;
    } 
    int i = Length_X, j = Length_Y;
    if (tag[i][j] == 0)
    {
        cout<<X[i-1]<<setw(4);
        Print_LCS(tag,X,i-1,j-1);
    }
    else if(tag[i][j] == 1)
    {
        Print_LCS(tag,X,i-1,j);
    }
    else
    {
        Print_LCS(tag,X,i,j-1);
    }
}

int main()
{
    //先人为设置两个序列
    char *X = "BDCABA";
    char *Y = "ABCBDA";
    int *count[7];
    for (int i = 0; i < 7; i++)
    {
        count[i] = new int[7];       //因为第一行第一列全为0,所以总共七行七列
    }
    int *tag[7];
    for (int i = 0; i < 7; i++)
    {
        tag[i] = new int[7];
    }
    LCS_Length(X,Y,count,tag,strlen(X),strlen(Y));
    cout<<"最大子序列数为"<<count[6][6]<<endl;
    /****************************************
    for(int i= 0; i <7; i++)
    {
        for (int j = 0; j < 7; j++)
        {
            cout<<count[i][j]<<setw(3);
        }
        cout<<endl;
    }
    *****************************************/
    Print_LCS(tag,X,strlen(X),strlen(Y));
    cout<<endl;
    return 0;
}

 

  主要函数有两个,一个函数是做出保存最长公共子序列的元素个数的矩阵,这里给出的示例中,两个字符串都各6个字符,所以给出的是7行7列矩阵(第一行第一列全为零)。

另外一个函数即为打印函数,从矩阵右下角一位开始遍历到[0][0]位,凡是遇到tag[i][j]标志为0则将该位的字符打印出来。算法比较简单易懂,具体可以参考《算法导论》。

 

下面补充说一个问题:二维指针到底怎么用。比如前面的二维数组初始化,如果我希望能够通过字符串的长度来给我的二维数组定义大小,而不是用常数来指定,使得我们可以通过strlen()函数来定义长度,那么就要用到二维指针。

注意:int *Arr[strlen(str)];这种声明方式是不正确的,编译器会提示错误,数组的声明必须使用常量。下面给出正确的示例:

        /***********************************************
    //华丽丽的分割线--------------------------------
    二维指针到底怎么用
    int *(*ptr) = new int*[strlen(X)];
    for (int i = 0; i < strlen(X); i++)
    {
        ptr[i] = new int[strlen(X)];
    }
    ptr[2][3] = 0;
    cout<<ptr[2][3]<<endl;
    **********************************************/

 

posted @ 2013-12-18 15:28  NeroHwang  阅读(529)  评论(0编辑  收藏  举报