大白话讲解LCS(最长公共子序列)
今天看了七月在线算法课。再一次认识了LCS,现在整理记录:
LCS(Longest Common Subsequence)最长公共子序列。
一个序列S任意删除若干个字符得到新序列T,那么T叫做S的子序列。
两个序列X和Y的公共子序列中,长度最长的那个叫X和Y的最长公共子序列。
例如:
字符串13455和245576的最长公共子序列为455.
字符串acdfg和adfc的最长公共子序列为adf.
注意:这里要区别最长公共子串LCS(Longest Common Substring),这个要求的是字符串必须连续。
这里偷懒,直接拿了老师的PPT。记好下面的记号。
下面就进行LCS解法的探索:
当x=y的时候:
然后我们就能得到:
此处的意思就是:当两个子序列中结尾字符是相等的,那么最长的子序列就肯定是这个相等值+前面的的最长长度了,这样他们的长度才能是最长的。
例子:
那么现在我们再考虑X不等于Y的情况:
此处的解释:
当我们认为是我们子序列的子串的最后一个元素不相等,那么他的最长子序列一定来自两个地方,假设去掉X序列的最后一个元素,那么最长子序列一定产生于图中A+B+Yn,同理一样, B+A+Xn.
例子:
总结:
怎么求呢?C[m,n]是一个正整数的值,表示序列m和n之间的最大的长度。
当两个字符串有一个是0 ,那么LCS一定是0;
例子:
右下角的数据怎么计算呢?
经过上面的分析,我们知道两个序列有一个是0 的那么LCS都是0 ;所以第0行第0列都是0.
图中红圈内1怎么得来的呢?
红圈内的x是B,y是D,即x不等于y.那么我们就要看红圈上左边和上边 的数值了,选择一个大的数值写入。
那么以此类推,当x=y 的时候,我们直接选择红圈左上的值+1,写入即可。
两个例子来自点击打开链接
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int LCSLength(char* str1, char* str2, int **b)
{ int i,j,length1,length2,len; length1 = strlen(str1); length2 = strlen(str2); //双指针的方法申请动态二维数组 int **c = new int*[length1+1]; //共有length1+1行 for(i = 0; i < length1+1; i++) c[i] = new int[length2+1];//共有length2+1列 for(i = 0; i < length1+1; i++) c[i][0]=0; //第0列都初始化为0 for(j = 0; j < length2+1; j++) c[0][j]=0; //第0行都初始化为0 for(i = 1; i < length1+1; i++) { for(j = 1; j < length2+1; j++) { if(str1[i-1]==str2[j-1])//由于c[][]的0行0列没有使用,c[][]的第i行元素对应str1的第i-1个元素 { c[i][j]=c[i-1][j-1]+1; b[i][j]=0; //输出公共子串时的搜索方向 } else if(c[i-1][j]>c[i][j-1]) { c[i][j]=c[i-1][j]; b[i][j]=1; } else { c[i][j]=c[i][j-1]; b[i][j]=-1; } } } /* for(i= 0; i < length1+1; i++) { for(j = 0; j < length2+1; j++) printf("%d ",c[i][j]); printf("\n"); } */ len=c[length1][length2]; for(i = 0; i < length1+1; i++) //释放动态申请的二维数组 delete[] c[i]; delete[] c; return len;
}
void PrintLCS(int **b, char *str1, int i, int j)
{ if(i==0 || j==0) return ; if(b[i][j]==0) { PrintLCS(b, str1, i-1, j-1);//从后面开始递归,所以要先递归到子串的前面,然后从前往后开始输出子串 printf("%c",str1[i-1]);//c[][]的第i行元素对应str1的第i-1个元素 } else if(b[i][j]==1) PrintLCS(b, str1, i-1, j); else PrintLCS(b, str1, i, j-1);
} int main(void)
{ char str1[100],str2[100]; int i,length1,length2,len; printf("请输入第一个字符串:"); gets(str1); printf("请输入第二个字符串:"); gets(str2); length1 = strlen(str1); length2 = strlen(str2); //双指针的方法申请动态二维数组 int **b = new int*[length1+1]; for(i= 0; i < length1+1; i++) b[i] = new int[length2+1]; len=LCSLength(str1,str2,b); printf("最长公共子序列的长度为:%d\n",len); printf("最长公共子序列为:"); PrintLCS(b,str1,length1,length2); printf("\n"); for(i = 0; i < length1+1; i++)//释放动态申请的二维数组 delete[] b[i]; delete[] b; system("pause"); return 0;
}
大白话讲解LCS(最长公共子序列)相关推荐
- 算法设计 - LCS 最长公共子序列最长公共子串 LIS 最长递增子序列
出处 http://segmentfault.com/blog/exploring/ 本章讲解: 1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度: 2. 与之类似但不 ...
- LCS最长公共子序列和LIS最长上升子序列——例题剖析
一.LCS最长公共子序列 最长公共子序列(LCS)问题算法详解+例题(转换成LIS,优化为O(nlogn),看不懂你来打我) longest comment subsequence 模板题 longe ...
- LCS(最长公共子序列)及其O(n)空间优化,O(nlogn)时间复杂度优化
LCS(最长公共子序列)及其O(n)空间优化,O(nlogn)时间复杂度优化 n^2 的版本 int LCS_n_2(vector<char> &a,vector<char& ...
- 动态规划求解LCS最长公共子序列问题c++
文章目录 求最长公共子序列 最长公共子序列问题 刻画最长公共子序列的特征 递归公式 C++代码 求最长公共子序列长度 打印任意一组最长公共子序列 模板题 求最长公共子序列 最长公共子序列问题 (Lon ...
- LCS(最长公共子序列)
题意描述 求两个字符串的最长公共子序列的长度 动态规划 用二维数组 C[i][j] 记录串x1x2⋯xi与y1y2⋯yj 的 LCS长度,则可得到状态转移方程: 代码实现: #include<i ...
- LCS/最长公共子序列/最长公共子串 实现 Python/Java
参考 http://blog.csdn.net/u012102306/article/details/53184446 http://blog.csdn.net/hrn1216/article/det ...
- LCS最长公共子序列(最优线性时间O(n))
这篇日志主要为了记录这几天的学习成果. 最长公共子序列根据要不要求子序列连续分两种情况. 只考虑两个串的情况,假设两个串长度均为n. 一,子序列不要求连续. (1)动态规划(O(n*n)) (转自:h ...
- POJ 1458 Common Subsequence DP LCS 最长公共子序列
最长公共子序列,照抄<算法设计与分析导论>P138-140 设输入的两个字符串分别为a1,a2,```,am(串a) b1,b2,````,bn(串b) 设d(i,j)为字符串a1,a2, ...
- LCS最长公共子序列
例如 b c d d e和 a c e e d e的公共子串为c d e. 如果使用暴力,复杂度太高会直接超时.就需要使用动态规划 dp[i][j]表示a串第i个结尾,b串第j个结尾的最长公共子串的数 ...
最新文章
- Element 'dependency' cannot have character [children]
- 网易智慧企业亮相TOP 100 Summit,以创新和匠心探索行业前沿
- 工业机器人工具中心点标定的意义_如何理解工业机器人的工具中心点
- sql语句优化之not in
- Split Temporary Variable(分解临时变量)
- python hack_Python进阶:深入GIL(上篇)
- Python使用Tornado+Redis维护ADSL拨号服务器代理池
- MySQL 字符串转in/double类型——CAST/CONVERT函数的用法
- Spring入门-框架搭建
- 日志存储 elasticsearch vs clickhouse
- Windows批处理BAT脚本
- oracle rac 在完成安装错误。
- IDEA的常用快捷键(超详细)
- 在python中安装包出现Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None))
- 【Kafka】ZK、Kafka以及EFAK的安装、配置
- 海南大学 838信号与系统专业课的感悟
- Java应用系列之Pinyin4j简单使用教程
- java倒计时器_java – 使用计时器倒计时
- Git配置、版本控制与分支管理
- 国内免费(开源)CMS系统【大全】