动态规划专练2 最长公共子序列问题

来源:互联网 发布:苏菲娜护肤品知乎 编辑:程序博客网 时间:2024/06/05 11:17

一、问题描述

求两个字符序列的公共最长子序列。例如字符序列abcbdb和字符序列acbbabdbb的最长公共子序列为acbdb。


二.基本概念知识(摘自博客):子序列基本概念
三:假如S1的最后一个元素 与 S2的最后一个元素相等,那么S1和S2的LCS就等于 {S1减去最后一个元素} 与 {S2减去最后一个元素} 的 LCS  再加上 S1和S2相等的最后一个元素。

       假如S1的最后一个元素 与 S2的最后一个元素不等(本例子就是属于这种情况),那么S1和S2的LCS就等于 : {S1减去最后一个元素} 与 S2 的LCS, {S2减去最后一个元素} 与 S1 的LCS 中的最大的那个序列。

四:递推公式:---dp[i][j]=dp[i-1][j-1]+1;(a[i]==b[j])

                                        =max(dp[i][j-1],dp[i-1][j])(a[i]!=b[j])

其中:i,j是指a,b数组中到第i,j个字符的字符串。

五。

       解决LCS问题,需要把原问题分解成若干个子问题,所以需要刻画LCS的特征。

       设A=“a0,a1,…,am”,B=“b0,b1,…,bn”,且Z=“z0,z1,…,zk”为它们的最长公共子序列。不难证明有以下性质:
       如果am=bn,则zk=am=bn,且“z0,z1,…,z(k-1)”是“a0,a1,…,a(m-1)”和“b0,b1,…,b(n-1)”的一个最长公共子序列;
       如果am!=bn,则若zk!=am,蕴涵“z0,z1,…,zk”是“a0,a1,…,a(m-1)”和“b0,b1,…,bn”的一个最长公共子序列;
       如果am!=bn,则若zk!=bn,蕴涵“z0,z1,…,zk”是“a0,a1,…,am”和“b0,b1,…,b(n-1)”的一个最长公共子序列。

六。代码以及输出最长序列(其中一个)

#include <stdio.h>#include<string.h>char a[1000],b[1000];//输入两个字符串int digit[1000][1000];//记录a到i同时b到j的最大长度int output[1000][1000];//用于输出标记char put[1000];//保存输出字符int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=EOF)    {        getchar();        memset(a,0,sizeof(a));        memset(b,0,sizeof(b));        memset(digit,0,sizeof(digit));        memset(put,0,sizeof(put));        gets(a);        gets(b);        int i,j;        for(i=0; i<n; i++)        {            for(j=0; j<m; j++)            {                if(a[i]==b[j])                {                    digit[i+1][j+1]=digit[i][j]+1;//长度加一                    output[i+1][j+1]=1;//此处标记为1                }                else if(digit[i+1][j]>=digit[i][j+1])//不然选子序列较大的那个                {                    digit[i+1][j+1]=digit[i+1][j];                    output[i+1][j+1]=2;//删掉b结尾较大,此处标记为2                }                else                {                    digit[i+1][j+1]=digit[i][j+1];//删掉a结尾较大,此处标记为3                    output[i+1][j+1]=3;                }            }        }        printf("最长公共子序列长度为: %d\n",digit[n][m]);        i=n,j=m;        int k=digit[n][m];        while(i>0&&j>0)        {            if(output[i][j]==1)//==1时为两子序列公共地方,存下来            {                put[k-1]=a[i-1];                i--;                j--;                k--;            }            else if(output[i][j]==2)//标记为2时是删掉b结尾导致的,顺着往上应该j--,下面同理                j--;            else                i--;        }        printf("最长公共子序列为: %s\n",put);    }    return 0;}

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 温岚和陆晋渊 夏天的风 温岚 温岚 祝我生日快乐 爱的代价 温岚 歌词 温岚好听的歌 生日快乐温岚 温岚 夏天的风 歌词 傻瓜歌词温岚 温岚生日快乐歌词 温岚 夏天的风 伴奏 夏天的风温岚mv 祝我生日快乐 温岚 生日快乐歌词温岚 祝我生日快乐温岚mv 祝我生日快乐温岚铃声 温岭 温岭市 温岭闲人 温岭石塘 温岭人才网 浙江温岭 温岭108社区 温岭新娘 温岭房产 温岭邮编 温岭火车站 温岭旅游 温岭景点 温岭站 温岭房价 温岭鞋厂 温岭周边游 温岭日报 温岭银泰城 温岭到晋江 温岭补习班 温岭一天游 温岭会计网 瑞安到温岭 浙江省温岭 椒江到温岭