最长公共子序列(LCS)算法

article/2025/9/11 12:16:51

一、最长公共字串与最长公共子序列

最长公共子串(Longest Common Substirng)

子串是串的一个连续的部分,子串中字符的位置必须连续

例如:有两个字符串ABCBDAB BDCABA,则它们的最长公共子串是:AB

最长公共子序列(Longest Common Subsequence,LCS)

子序列是从串中去掉任意的元素而获得新的序列,子串中字符的位置不必连续

例如:有两个字符串ABCBDAB BDCABA,则它们的最长公共子序列是:BCAB


二、LCS算法

step1:生成矩阵

创建一个大小为str1_len×str2_len的矩阵,其中str1_lenstr2_len分别为串str1和串str2的长度,初始化为0

按照以下规则生成矩阵:

i和j分别从1开始,i++,j++循环

  • 如果str1[i] == str2[j],则L[i,j] = L[i - 1, j -1] + 1

  • 如果str1[i] != str2[j],则L[i,j] = max{L[i,j - 1],L[i - 1, j]}

void init_array(char *str1, char *str2) {int i,j;for(i=1; i<=str1_len; i++)for(j=1; j<=str2_len; j++) {if(str1[i-1] == str2[j-1])a[i][j] = a[i-1][j-1] + 1;else {if(a[i][j-1] >= a[i-1][j])a[i][j] = a[i][j-1];elsea[i][j] = a[i-1][j];}}
}

step2:计算公共子序列

按照以下规则计算公共子序列:

ij分别从str1_lenstr2_len开始,递减循环直到i = 0,j = 0

  • 如果str1[i-1] == str2[j-1],则将str[i]字符插入到子序列中,i--,j--

  • 如果str1[i-1] != str[j-1],则比较L[i,j-1]L[i-1,j]L[i,j-1]大,则j--,否则i--;(如果相等,则任选一个

LCS

void parser(char *str1, char *str2, char *res) {int i,j,k = 0;for(i = str1_len, j = str2_len; i >= 1 && j >= 1;) {if(str1[i-1] == str2[j-1]) {res[k++] = str1[i-1];i--;j--;} elseif (a[i][j-1] > a[i-1][j])j--;elsei--;}
}

step3:逆序存放公共子序列

step2得到的公共子序列是从后往前获得的,需要逆序存放或输出

char* reverse(char *str) {int n = strlen(str) / 2;int i = 0;char tmp;for(i=0; i<n; i++) {tmp = str[i];str[i] = str[strlen(str)-i-1];str[strlen(str)-i-1] = tmp;}return str;
}

三、完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_LEN 256int str1_len, str2_len;
int a[MAX_LEN][MAX_LEN];void init_str(char *str1, char *str2) {printf("please input str1: ");scanf("%s", str1);printf("please input str2: ");scanf("%s", str2);
}void init_array(char *str1, char *str2) {int i,j;for(i=1; i<=str1_len; i++)for(j=1; j<=str2_len; j++) {if(str1[i-1] == str2[j-1])a[i][j] = a[i-1][j-1] + 1;else {if(a[i][j-1] >= a[i-1][j])a[i][j] = a[i][j-1];elsea[i][j] = a[i-1][j];}}
}void parser(char *str1, char *str2, char *res) {int i,j,k = 0;for(i = str1_len, j = str2_len; i >= 1 && j >= 1;) {if(str1[i-1] == str2[j-1]) {res[k++] = str1[i-1];i--;j--;} elseif (a[i][j-1] > a[i-1][j])j--;elsei--;}
}char* reverse(char *str) {int n = strlen(str) / 2;int i = 0;char tmp;for(i=0; i<n; i++) {tmp = str[i];str[i] = str[strlen(str)-i-1];str[strlen(str)-i-1] = tmp;}return str;
}int main(void) {char str1[MAX_LEN], str2[MAX_LEN], *res;init_str(str1, str2);str1_len = strlen(str1);str2_len = strlen(str2);init_array(str1, str2);res = (char*)malloc(sizeof(char) * (str1_len + str2_len));parser(str1, str2, res);printf("Result : %s\n", reverse(res));return 0;
}

四、牛刀小试

POJ 1458 Common Subsequence

Description
A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, …, xm > another sequence Z = < z1, z2, …, zk > is a subsequence of X if there exists a strictly increasing sequence < i1, i2, …, ik > of indices of X such that for all j = 1,2,…,k, xij = zj. For example, Z = < a, b, f, c > is a subsequence of X = < a, b, c, f, b, c > with index sequence < 1, 2, 4, 6 >. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.

Input
The program input is from the std input. Each data set in the input contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct.

Output
For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.

Sample Input

abcfbc abfcab
programming contest
abcd mnp

Sample Output

4
2
0

Code

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (sc.hasNext()) {String[] tmp = sc.nextLine().trim().split("\\s+");String str1 = tmp[0];String str2 = tmp[1];int[][] data = new int[str1.length() + 1][str2.length() + 1];for (int i = 1; i < data.length; i++)for (int j = 1; j < data[i].length; j++) {if (str1.charAt(i - 1) == str2.charAt(j - 1)) {data[i][j] = data[i - 1][j - 1] + 1;} else {data[i][j] = Math.max(data[i][j - 1], data[i - 1][j]);}}System.out.println(data[str1.length()][str2.length()]);}}
}

http://chatgpt.dhexx.cn/article/do5ApsTm.shtml

相关文章

LCS(longest common sequence)算法的实现(十分详细)

一、问题描述 有两个字符串&#xff0c;求二者的最长公共子序列。 最长公共子序列&#xff1a;不必连续但必须有序的子列&#xff08;与子串区分&#xff0c;子串是连续的&#xff09; 二&#xff1a;解决方法 第一种方法&#xff1a;穷举法 &#xff0c;就是一个一个的对比&a…

LCS算法

LCS算法 LCS算法&#xff1a; LCS是Longest Common Subsequence的缩写&#xff0c;即最长公共子序列。一个序列&#xff0c;如果是两个或多个已知序列的子序列&#xff0c;且是所有子序列中最长的&#xff0c;则为最长公共子序列。LCS不是唯一的&#xff0c;它可以有很多种&am…

Oracle中索引的原理

索引的概念 索引是一种数据库结构&#xff0c;能够就数据库中的某列提供快速查询&#xff0c;而不用检索整个表格&#xff08;官方的不行&#xff09;。 在 Oracle 数据库中&#xff0c;存储的每一行数据都有一个 rowID 来标识。当 Oracle 中存储着大量的数据时&#xff0c;意…

MongoDB索引原理及实践

背景 数据库的演进 随着计算机的发展&#xff0c;越来越多的数据需要被处理&#xff0c;数据库是为处理数据而产生。从概念上来说&#xff0c;数据库是指以一定的方式存储到一起&#xff0c;能为多个用户共享&#xff0c;具有更可能小的冗余&#xff0c;与应用程序彼此独立的…

MySql存储引擎和索引原理

转载 https://blog.csdn.net/tongdanping/article/details/79878302 注意&#xff1a; 1、索引需要占用磁盘空间&#xff0c;因此在创建索引时要考虑到磁盘空间是否足够 2、创建索引时需要对表加锁&#xff0c;因此实际操作中需要在业务空闲期间进行 MySQL支持诸多存储引擎&a…

MySQL之索引原理

1 简介 索引底层就是一种数据结构&#xff0c;空间换时间&#xff0c;能够帮助我们快速定位到对应的数据&#xff0c;就类似于字典里面的目录一样。 索引虽然能快速检索数据&#xff0c;但会影响数据修改的操作&#xff0c;而且索引存储在具体的文件&#xff0c;占用一定的空…

深入浅出数据库索引原理

使用索引很简单&#xff0c;只要能写创建表的语句&#xff0c;就肯定能写创建索引的语句&#xff0c;要知道这个世界上是不存在不会创建表的服务器端程序员的。然而&#xff0c; 会使用索引是一回事&#xff0c; 而深入理解索引原理又能恰到好处使用索引又是另一回事&#xff0…

MySQL索引原理和实现

说到索引&#xff0c;很多人都知道“索引是一个排序的列表&#xff0c;在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址&#xff0c;在数据十分庞大的时候&#xff0c;索引可以大大加快查询的速度&#xff0c;这是因为使用索引后可以不用扫描全表来定位某行的数…

倒排索引原理,即为什么叫倒排索引

倒排索引的英文原名是Inverted index&#xff0c;大概因为Invert有颠倒的意思&#xff0c;所以就被翻译成了倒排&#xff0c;然后我们就会在字面上出现误解&#xff1a;理解为从A-Z颠倒成Z-A。其实它并不是字面上的意思。 倒排索引源于实际应用中需要根据属性的值来查找记录&a…

【数据库】数据库索引原理

正确的创建合适的索引 是提升数据库查询性能的基础 文章目录 1.索引是什么&#xff1f;2.为什么&#xff1f;3.索引原理B tree 4.B tree 在两大引擎中的体现5.索引的原则 1.索引是什么&#xff1f; 索引是为了加速对表中数据行的检索而创建的一种分散存储的数据结构。 2.为…

Mysql数据库的索引原理

写在前面&#xff1a;索引对查询的速度有着至关重要的影响&#xff0c;理解索引也是进行数据库性能调优的起点。考虑如下情况&#xff0c;假设数据库中一个表有10^6条记录&#xff0c;DBMS的页面大小为4K&#xff0c;并存储100条记录。如果没有索引&#xff0c;查询将对整个表进…

MySql索引原理与使用大全

林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka 一、索引介绍 索引是对数据库表中一列或多列的值进行排序的一种结构。在关系数据库中&#xff0c;索引是一种与表有关的数据库结构&#xff0c;它可以使对应于表的SQL语句执行得更快。索引的作用相…

MySQL:索引原理

文章目录 1、索引概念1.1、使用场景1.2、索引代价 2、索引分类2.1、数据结构2.2、物理存储回表查询 & 覆盖索引 2.3、字段&#xff08;列&#xff09;属性2.3.1、主键索引主键的选择 2.3.2、唯一索引2.3.2、普通索引2.3.3、前缀索引 2.4、字段&#xff08;列&#xff09;个…

索引的原理和实现的方式

建立索引 需要有索引的类型和索引的方法。 索引的类型包括了Normal Unique Full text 而索引的方法包括了BTREE 和HASH 转载文章&#xff1a;https://www.cnblogs.com/aspwebchh/p/6652855.html 博主写的真好~ 一、什么是Btree B tree &#xff08;非二叉&#xff09; 了…

索引的实现原理

这篇文章是介绍MySQL数据库中的索引是如何根据需求一步步演变最终成为B树结构的以及针对B树索引的查询&#xff0c;插入&#xff0c;删除&#xff0c;更新等操作的处理方法。Oracle和DB2数据库索引的实现基本上也是大同小异的。文章写得很通俗易懂&#xff0c;就转在这了。关于…

MySQL索引的理解学习,面试不问索引原理就是事务原理

目录 MySQL执行SQL的整体流程 引言, MySQL索引底层学习原因 磁盘介绍(理解磁盘IO) 索引底层数据结构B树 B树(聚集索引) B树(辅助索引) 思考一下为何使用B树结构, 不是B树, 不是平衡树二叉树,红黑树&#xff1f; 索引总结 MySQL执行SQL的整体流程 显示需要跟MYSQL Serv…

Git | 面试官问你 Git 原理,你能回答得出来吗?

文章目录 原创声明前言一、Git 简单介绍二、解开 Git 在日常上班操作中的神秘面纱2.1 初始化仓库git init 2.2 第n次提交git add xxxgit statusgit commit -m "xxx" 2.3 分支2.3.1 创建分支 git branch xxx2.3.2 切换分支 git checkout 2.3.3 分支中提交 总结参考资料…

Git概念及工作原理总结

Git是分布式版本控制系统。Github和华为等均使用Git作为代码管理工具。之前在工作中比较常用到的是克隆、代码提交拉取、解决回合冲突、代码回滚等。在实际的工作中&#xff0c;可能回合时冲突及版本回退的情况较多&#xff0c;下文将着重介绍这两点。本文不涉及Git的安装等&am…

Git 天天用 但是 Git 原理你了解吗?

前言 做技术一定要知其然知其所以然&#xff0c;意思就是&#xff1a;知道它是这样的&#xff0c;更知道它为什么是这样的。我主要通过4块内容来简单介绍 Git 原理是什么样的。这4块内容如下&#xff1a; Git 存储目录结构介绍Git 是如何存储的Git 的对象Git引用 当然 Git 原…

(一篇就够)git原理深入理解

深入理解git原理 1&#xff1a;git工作模式 基本步骤&#xff1a; 1.workspace 本地工作空间add命令 提交到本地缓存 2、localcache本地缓存commit命令提交到本地仓库 3、localRepository本地仓库push命令提交到远程仓库 拉取步骤&#xff1a; clone 克隆到本地仓库 checkout…