最长公共子序列的C++实现代码

来源:互联网 发布:java构造方法调用顺序 编辑:程序博客网 时间:2024/04/29 15:41

引进一个二维数组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]。

这里需要注意的是c[i][j]对应的是以data1[i-1],data2[j-1]结束的子串的最长公共子序列。

问题的递归式写成:


recursive formula

回溯输出最长公共子序列过程:

flow

 

算法分析:
由于每次调用至少向上或向左(或向上向左同时)移动一步,故最多调用(m + n)次就会遇到i = 0或j = 0的情况,此时开始返回。返回时与递归调用时方向相反,步数相同,故算法时间复杂度为Θ(m + n)。

#include <iostream>

#include <vector>

using namespace std;

void Print(const vector<int> &data1,vector<vector<int> > arrayPos,int x,int y)
{
    if(x<0||y<0)

        return;

//这种情况下data1[x]肯定不在公共子序列,故可以将问题规模减一

//改成data1打印从0到x-1

    else if(arrayPos[x][y]==1)
    {
        Print(data1,arrayPos,x-1,y);
    }
    else if(arrayPos[x][y]==-1)
    {
        Print(data1,arrayPos,x,y-1);

    }

//data1[x]在公共子序列中,打印之

//需要注意的是在递归调用后才打印

    else if(arrayPos[x][y]==0)
    {
        Print(data1,arrayPos,x-1,y-1);
        cout<<data1[x]<<" ";
    }
}

void MaxSameSeq(const vector<int> &data1,const vector<int> &data2)
{
     int num1=data1.size();

     int num2=data2.size();

//记录以data1的第i个元素和data2的第j个元素结尾的两个子串的公共子序列长

//这里的i,j均是从1开始

     vector<vector<int> > arrayLong(num1+1,vector<int>(num2+1,0));
     vector<vector<int> > arrayPos(num1,vector<int>(num2,0));
     for(int i=0;i<=num1;i++)
     {
        arrayLong[i][0]=0;
     }
     for(int j=0;j<=num2;j++)
     {
         arrayLong[0][j]=0;
     }

     for(i=1;i<=num1;i++)
     {
         for(j=1;j<=num2;j++)

         {

//第i个元素就是data1[i-1]

//第j个元素就是data2[j-1]

             if(data1[i-1]==data2[j-1])
             {

                 arrayLong[i][j]=arrayLong[i-1][j-1]+1;

//表示data1[i],data2[j-1]在最长子序列中

                 arrayPos[i-1][j-1]=0;
             }
             else
             {
                 if(arrayLong[i-1][j]>arrayLong[i][j-1])
                 {

                     arrayLong[i][j]=arrayLong[i-1][j];

//表示data2[j]在最长子序列中

//data1[i]不在

                     arrayPos[i-1][j-1]=1;

                 }

//表示data2[j]不在最长子序列中

//data1[i]在不在都有可能

                 else
                 {
                     arrayLong[i][j]=arrayLong[i][j-1];
                     arrayPos[i-1][j-1]=-1;
                 }
             }
         }
     }

    cout<<"the long of the sequence:"<<arrayLong[num1][num2]<<endl;
    cout<<"the sequence:"<<endl;

    Print(data1,arrayPos,num1-1,num2-1);

    cout<<endl;
}


int main()
{
    cout<<"input the size of the 2 array:"<<endl;
    int num1,num2;
    cin>>num1>>num2;
    vector<int> arr1(num1,0);
    vector<int> arr2(num2,0);
    cout<<"input array1:"<<endl;
    for(int i=0;i<num1;i++)
        cin>>arr1[i];
    cout<<"input array2:"<<endl;
    for(i=0;i<num2;i++)
        cin>>arr2[i];
    MaxSameSeq(arr1,arr2);
    return 1;
}

原创粉丝点击