动态规划之最长公共子序列

子序列与子串不同,子串一定要连续,子序列可以不连续!
对于给定的两个序列 X{x1, x2, x3, … },Y{y1, y2, y3, …};求X与Y的最长公共子序列,可采用动态规划的方法。
1.当x1 = y1时,则此时已找到一个相同的值,故接下来只需求{x2, x3, x4, …}和{y2, y3, y4, …}的LCS。
2.当x1 != y1时,则此时X和Y的LCS是下面两个LCS的最大值:
{x2, x3, x4, …}和{y1, y2, y3, y4, …}的LCS,
或者{x1, x2, x3, x4, …}和{y2, y3, y4, …}的LCS。
由上面可以看出这是一个递归问题。
求解:
第一步:先计算最长公共子序列的长度。

第二步:根据长度,然后通过回溯求出最长公共子序列。

即:
这里写图片描述

代码如下:

#include <iostream>
#include <cstring>
using namespace std;
char x[100];
char y[100];
int c[100][100];//二维矩阵存储公共子序列长度
int max(int a,int b);
char *LCS(char x[],char y[]);//求最长公共子序列

int main(){

    int x1,y1;//两个字符串的长度
    cout<<"请分别输入第一、二个字符串长度"<<endl;
    cin>>x1>>y1; 
    cout<<"输入第一个字符串"<<endl;
    for(int i=0;i<x1;i++){
        cin>>x[i];
    }
    cout<<"输入第二个字符串"<<endl;
    for(int i=0;i<y1;i++){
        cin>>y[i];
    }

    char *s=LCS(x,y);
    cout<<"最长公共子序列为:"<<s<<endl;
    cout<<"长度为:"<<strlen(s)<<endl;
    return 0;
}
char *LCS(char x[],char y[]){
    int x1=strlen(x);
    int y1=strlen(y);

    for(int i=0;i<x1;i++)
    {
        c[i][0]=0;
    }
    for(int i=0;i<y1;i++){
        c[0][i]=0;
    }
    for(int i=0;i<x1;i++){//填充矩阵
        for(int j=0;j<y1;j++){
            if(x[i]==y[j]){//相等的情况
                c[i+1][j+1]=c[i][j]+1;
            }
            else{//不等,选大的
                c[i+1][j+1]=max(c[i][j+1],c[i+1][j]);
            }
        }
    }
    int len=c[x1][y1];
    int count=len;
    char * lcs=new char[len+1];
    while(x1>0&&y1>0){//回溯法求解子序列
        if(c[x1][y1]==c[x1-1][y1-1]+1&&x[x1-1]==y[y1-1]){
        //判断序列中是否有子序列的元素
            lcs[--count]=x[x1-1];
            x1--;
        }
        else if(c[x1][y1]==c[x1][y1-1]){
            y1--;
        }
        else{
            x1--;
        }
    }
    return lcs;
}

int max(int a,int b){
    if(a>=b){
        return a;
    }
    else 
        return b;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值