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

来源:互联网 发布:渣到触画画的过程知乎 编辑:程序博客网 时间:2024/06/13 20:51

子序列与子串不同,子串一定要连续,子序列可以不连续!
对于给定的两个序列 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;}
原创粉丝点击