最长公共子序列问题求解(LCS问题求解)

问题描述:输入两个字符串,求其最长公共子序列(公共子序列不要求子序列是连续的)

思路:假设序列长度分别为m,n的序列X=<_{^{^{^{^{^{}}}}}}x0,x1,x2...xm>,Y=<y0,y1,y2...yn>,其公共子序列为Z=<z1,z2...zk>,则存在

1、若xm=yn,则zk=xm=yn, Zk-1为Xm-1和Yn-1的最长公共子序列

2、若xm!=yn且zk!=xm,则Zk为Xm-1和Yn的最长公共子序列

3、若xm!=yn且zk!=yn,则Zk为Xm和Yn-1的最长公共子序列

总结:

LCS(Xm,Yn)=\left\{\begin{matrix}LCS(Xm-1,Yn-1)+1 & Xm=Yn & \\ max(LCS(Xm,Yn-1),LCS(Xm-1,Yn))& Xm!=Yn & \end{matrix}\right.

动态规划描述:

定义一个二维数组c[m+1][n+1]

c[i][j]=\left\{\begin{matrix}0 & i=0 &or& j=0 & \\ c[i-1][j-1]+1 & i>0,j>0&x[i] =y[j] & \\ max(c[i-1][j],c[i][j-1]) & i>0,j>0&x[i]! =y[j] & \end{matrix}\right.

#include <iostream>
#include<string.h>

using namespace std;
int getMax(int a,int b)
{
    return (a>b?a:b);
}

int  findLCS(const char * a,const char *b)
{
    int lenA=strlen(a);
    int lenB=strlen(b);

    int **c=new int*[lenA+1] ;
    for(int i=0;i<lenA+1;i++)
    {
        c[i]=new int[lenB+1];
    }

    for(int i=0;i<lenA;i++)
        c[i][0]=0;
    for(int j=0;j<lenB;j++)
        c[0][j]=0;


    for(int i=1;i<=lenA;i++)
    {
        for(int j=1;j<=lenB;j++)
        {
            if(a[i]==b[j])
            {
                c[i][j]=c[i-1][j-1]+1;
            }
            else
            {
                c[i][j]=getMax(c[i-1][j],c[i][j-1]);
            }
        }
    }
    
    int res=c[lenA][lenB];

    for(int i=0;i<lenA+1;i++)
        delete []c[i];
    delete c;
    return res;   
}

int main()
{
    char a[100]="abcbdab";
    char b[100]="bdcaba";
    int **c=findLCS(a,b);
    cout<<c[strlen(a)][strlen(b)]<<endl;
    cout<<findLCS(a,b)<<endl;
    return 0;
}

运行结果:

4

猜你喜欢

转载自blog.csdn.net/u013069552/article/details/81110620