博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
最长公共子序列求解:递归与动态规划方法
阅读量:6653 次
发布时间:2019-06-25

本文共 2609 字,大约阅读时间需要 8 分钟。

  在做OJ题目的时候,经常会用到字符串的处理。例如,比较二个字符串相似度。这篇文章介绍一下求两个字符串的最长公共子序列。

  一个字符串的子序列,是指从该字符串中去掉任意多个字符后剩下的字符在不改变顺序的情况下组成的新字符串。

  最长公共子序列,是指多个字符串可具有的长度最大的公共的子序列。

  (1)递归方法求最长公共子序列的长度

    1)设有字符串a[0...n],b[0...m],下面就是递推公式。

             当数组a和b对应位置字符相同时,则直接求解下一个位置;当不同时取两种情况中的较大数值。

    

    2)代码如下:

#include
#include
char a[30],b[30];int lena,lenb;int LCS(int,int);  ///两个参数分别表示数组a的下标和数组b的下标int main(){ strcpy(a,"ABCBDAB"); strcpy(b,"BDCABA"); lena=strlen(a); lenb=strlen(b); printf("%d\n",LCS(0,0)); return 0;}int LCS(int i,int j){ if(i>=lena || j>=lenb) return 0; if(a[i]==b[j]) return 1+LCS(i+1,j+1); else return LCS(i+1,j)>LCS(i,j+1)? LCS(i+1,j):LCS(i,j+1);}

     用递归的方法优点是编程简单,容易理解。缺点是效率不高,有大量的重复执行递归调用,而且只能求出最大公共子序列的长度,求不出具体的最大公共子序列。

  (2)动态规划求最长公共子序列的长度

    动态规划采用二维数组来标识中间计算结果,避免重复的计算来提高效率。

    1)最长公共子序列的长度的动态规划方程

    设有字符串a[0...n],b[0...m],下面就是递推公式。字符串a对应的是二维数组num的行,字符串b对应的是二维数组num的列。

    

    另外,采用二维数组flag来记录下标ij的走向。数字"1"表示,斜向下;数字"2"表示,水平向右;数字"3"表示,竖直向下。这样便于以后的求解最长公共子序列。

    (2)求解公共子序列代码

#include
#include
char a[500],b[500];char num[501][501]; ///记录中间结果的数组char flag[501][501]; ///标记数组,用于标识下标的走向,构造出公共子序列void LCS(); ///动态规划求解void getLCS(); ///采用倒推方式求最长公共子序列int main(){ int i; strcpy(a,"ABCBDAB"); strcpy(b,"BDCABA"); memset(num,0,sizeof(num)); memset(flag,0,sizeof(flag)); LCS(); printf("%d\n",num[strlen(a)][strlen(b)]); getLCS(); return 0;}void LCS(){ int i,j; for(i=1;i<=strlen(a);i++) { for(j=1;j<=strlen(b);j++) { if(a[i-1]==b[j-1]) ///注意这里的下标是i-1与j-1 { num[i][j]=num[i-1][j-1]+1; flag[i][j]=1; ///斜向下标记 } else if(num[i][j-1]>num[i-1][j]) { num[i][j]=num[i][j-1]; flag[i][j]=2; ///向右标记 } else { num[i][j]=num[i-1][j]; flag[i][j]=3; ///向下标记 } } }}void getLCS(){ char res[500]; int i=strlen(a); int j=strlen(b); int k=0; ///用于保存结果的数组标志位 while(i>0 && j>0) { if(flag[i][j]==1) ///如果是斜向下标记 { res[k]=a[i-1]; k++; i--; j--; } else if(flag[i][j]==2) ///如果是斜向右标记 j--; else if(flag[i][j]==3) ///如果是斜向下标记 i--; } for(i=k-1;i>=0;i--) printf("%c",res[i]);}

    (3)图示

    

类似有: 

参考:

http://www.cnblogs.com/huangxincheng/archive/2012/11/11/2764625.html

转载于:https://www.cnblogs.com/xudong-bupt/archive/2013/03/15/2959039.html

你可能感兴趣的文章
第二章 ESXi 安装和Sphere Client 5.0
查看>>
pycharm在创建.py文件时自动添加前缀
查看>>
dhcp
查看>>
Windows Server 2012显示桌面图标
查看>>
linux 复制多个文件夹下的文件到一个文件夹下面
查看>>
ORACLE 日期加减操作
查看>>
写博客的那点缘由
查看>>
教你如何将GNS3的默认telnet软件改为用SecureCRT启动
查看>>
python getopt使用
查看>>
一步一步Wpartition之partition什么时候使用
查看>>
修改linux主机名
查看>>
This is my demo
查看>>
刘启成_shell脚本应用实战
查看>>
前段时间参加个访谈,题目……不让我修改,我是典型的穷人啊……以下是访谈稿...
查看>>
参考博客配置IIS时遇到的问题记录
查看>>
poj - 3254 - Corn Fields (状态压缩)
查看>>
纯js写图片轮播插件
查看>>
DNS
查看>>
【转载】C++ Interesting卡常数
查看>>
Jlink-10 pin 的定义(stm32使用)官方定义
查看>>