字符串相似度算法完全指南:编辑、令牌与序列三类算法的全面解析与深入分析

在自然语言处理领域,人们经常需要比较字符串,这些字符串可能是单词、句子、段落甚至是整个文档。如何快速判断两个单词或句子是否相似,或者相似度是好还是差。这类似于我们使用手机打错一个词,但手机会建议正确的词来修正它,那么这种如何判断字符串相似度呢?本文将详细介绍这个问题。

字符串相似度

当我们有两个数字时,我们可以通过从一个数字中减去另一个数字并观察结果的符号和大小来轻松比较它们。这种比较方式也可以用于向量,并且有许多方法可以做到这一点。例如常见的:余弦距离、欧几里得距离、曼哈顿距离、闵可夫斯基公式的p距离等等

但是对于字符串来说就比较复杂了,因为有时需要比较单词、句子或一般的字符串。一种简单的方法是比较字符串或单词之间的公共字母。

总的来说,有三种主要类型的算法用于衡量字符串的相似度,我们将一一介绍:

  1. 基于编辑的算法
  2. 基于令牌的算法
  3. 基于序列的算法

基于编辑的算法

基于编辑的算法,也被称为基于距离的算法,通过测量将一个字符串转换成另一个字符串所需的最少单字符操作(插入、删除或替换)数量来衡量。操作次数越多,相似度(距离)就越低(高)。这一指标为许多其他字符串相似度技术提供了基础,并广泛用于拼写检查、自动纠错和DNA序列分析。

注意:这里的每个字符和每个操作都具有相同的重要性

1、Hamming 距离

该度量标准用于测量两个等长字符串的不相似度,方法是将一个字符串叠加在另一个字符串上,并计算有多少位置的字符不同。汉明要求是长度一致的,但是一些库可以忽略长度条件,所以算法并不适用于处理长度不相同的2个字符串。

 >> import textdistance as td
 >> td.hamming('book', 'look')
 1
 >> td.hamming.normalized_similarity('book', 'look')
 0.75
 >> td.hamming('bellow', 'below')
 3
 >> td.hamming.normalized_similarity('Below', 'Bellow')
 0.5

在第一个示例中,有一个不同的字符。这使得距离等于1,归一化相似度等于(4-1)/4 = 75%。在第二个示例中,比较“bellow”和“below”,前三个字母相同,但接下来的三个字母不同。因此,距离是3,归一化相似度是(6-3)/6 = 50%。

2、Levenshtein 距离

Levenshtein 距离是最常用的基于编辑的算法,是一个字符串相似度度量标准,用于测量将一个字符串转换成另一个字符串所需的最少单字符允许操作(插入、删除或替换)的数量。它提供了一个量化的度量,表明两个字符串有多不同。它没有像Hamming 距离那样的序列长度条件。

 >> td.levenshtein('book', 'look')
 1
 >> td.levenshtein.normalized_similarity('book', 'look')
 0.75
 >> td.levenshtein('bellow', 'below')
 1
 >> td.levenshtein.normalized_similarity('Below', 'Bellow')
 0.84

在第一个示例中,可以通过替换一个字母来得到另一个单词,因此归一化相似度是(4-1)/4 = 75%。在第二个示例中,有一个插入操作,因此距离是1,归一化相似度是(6-1)/6 = 84%。

3、Damerau-Levenshtein距离

Damerau-Levenshtein距离是Levenshtein 距离的一个变种,它还包括了置换操作。它测量转换一个字符串到另一个字符串所需的四种操作的数量。置换涉及交换两个相邻字符。

注意:不能置换两个不相邻的符号,因此,“stop”和“spot”之间的距离不是1,而是两次(两次替换)。

 >> td.levenshtein('act', 'cat')
 2
 >> td.levenshtein.normalized_similarity('act', 'cat')
 0.34
 >> td.damerau_levenshtein('act', 'cat')
 1
 >> td.damerau_levenshtein.normalized_similarity('act', 'cat')
 0.67

Levenshtein需要替换两个字母‘a’和‘c’,但由于这两个字母是相邻的,我们可以使用Damerau-Levenshtein算法通过一次操作进行置换,这样就使相似度结果翻倍。这种算法在自然语言处理领域得到了广泛应用,如拼写检查和序列分析。

4、Jaro 相似度

这个算法不是一种距离测量,而是一个介于0和1之间的相似度得分。

Jaro 算法基于匹配字符的数量以及类似Damerau-Levenshtein的置换,但它没有邻近性约束。该方法使用了一个直观的公式:

只有当s1和s2中的两个字符相同且相距不超过max(|s1|, |s2|)/2 - 1个字符时,才被视为匹配。

如果没有找到匹配字符,那么这两个字符串就被认为不相似,贾罗相似度为0。但如果找到了匹配字符,那么我们就计算置换的数量。

 >> td.jaro('bellow', 'below')
 0.94
 >> td.jaro('simple', 'plesim')
 0
 >> td.jaro('jaro', 'ajro')
 0.92

在第一个示例中,有5个匹配字符和一个插入(这不是置换操作),因此Jaro 相似度为1/3*(5/6+5/5+6/6)。在第二个示例中,有0个匹配字符,因为共同字符不在max(|s1|, |s2|)/2-1的范围内。这就是为什么相似度为0的原因。在最后一个示例中,有4个匹配字符和第一和第二字母之间的1个置换操作,因此相似度为1/3 * (4/4+4/4+3/4) = 0.91。

5、Jaro-Winkler相似度

Jaro-Winkler相似度是Jaro相似度的一种修改。它旨在给字符串的公共前缀更多的权重。这将使得前l个字符相同的字符串得到更高的分数。其公式为:

 >> td.jaro("simple", "since")
 0.7
 >> t.jaro_winkler("simple", "since")
 0.76

由于两个字符串有两个共同的前缀字母。Jaro-Winkler相似度大于Jaro相似度:0.7 + 0.12(1–0.7) = 0.7 + 0.06 = 0.76。

6、Smith–Waterman相似度

Smith–Waterman算法是一种动态规划算法,用于寻找两个序列之间的最优局部对齐。与寻找最优全局对齐的Needleman-Wunsch算法不同,Smith–Waterman算法识别序列内最佳匹配的子序列,这使其比Needleman-Wunsch算法更具相关性。

该算法基于一个评分矩阵为每个可能的局部对齐分配一个分数,该矩阵定义了字符对之间的相似性或不相似性。它寻找序列中得分最大的区域,表示最佳的局部匹配。

Smith–Waterman算法在生物信息学中特别有用,用于识别生物序列中的相似区域或基序,如DNA或蛋白质序列,而不是寻找整个序列的相似性。它允许检测可能具有生物学意义的局部相似性。

 >> td.smith_waterman("GATTACA", "GCATGCU")
 3
 >> td.smith_waterman("GATTACA", "GCATGCU")
 0.43

基于令牌的算法

基于令牌的算法侧重于根据字符串的构成令牌或单词(但有时令牌只是字符)比较字符串。

1、Jaccard 相似度

Jaccard 距离是衡量两个集合之间相似度的一种方法。它通过比较集合中的共享元素与它们总的组合元素来量化集合的相似程度。要计算它,你需要找到交集(共享元素)的大小除以并集(所有独特元素)的大小。

 >> td.jaccard('jaccard similarity'.split(), "similarity jaccard".split())
 1
 >> td.jaccard('jaccard similarity'.split(), "similarity jaccard jaccard".split())
 0.66

我们可以看到,Jaccard 相似度并不考虑字符串单词的顺序。

textdistance包的实现考虑了重复元素,但使用上述公式的经典算法在第二个示例中会给出1的结果。如果你没有将序列分割成单词,算法将会将其分割成字符,并对它们应用Jaccard 公式。

如果你了解过目标检测的算法,你会常听到过一个单词 “交并比(Intersection of Union,IoU)”他其实计算的就是Jaccard 相似度。

2、Sørensen-Dice 相似度

Sørensen-Dice 相似度或系数是一种衡量两个集合之间相似度的指标,类似于Jaccard 相似度。它常用于数据分析、文本挖掘和图像处理等领域。你最常听到的一个名字是Dice系数,就是它了。

它的计算方法是找到两个集合之间共享元素(交集)数量的两倍与集合大小之和的比例。相似度的公式如下:

 >> td.sorencen('jaccard similarity'.split(), "similarity jaccard".split())
 1
 >> td.sorencen('jaccard similarity'.split(), "similarity jaccard jaccard".split())
 0.8

如果用集合的角度看,把相交作为正类,不相交作为负类,那么我们比较的相似度应该是预测为正类的集合与真实正类集合两者之间的相似度,换成上述四个值理解,也就是:

我们再看看f1score的计算公式

F1-score和Dice是相等的,就是这样。

Sørensen-Dice 相似度与Jaccard 相似度唯一的区别是前者更强调共享元素。

Sørensen-Dice相似度在处理二进制数据或元素的存在与否很重要的情况下特别有用。它提供了一种衡量相似度的方法,考虑了集合的大小并强调了共享元素。

它们之间的关系是:

3、Tversky 相似度

Tversky 指数是一种相似度算法,用于量化两个集合之间重叠的程度,同时考虑到假阳性和假阴性。它在处理不平衡数据或集合中元素的存在或缺失具有不同重要性的情况下特别有用。我们可以选择强调共有的词(字符)或非共享的词。

其定义公式如下:

Tversky基指数可以被视为Sørensen-Dice 和Jaccard 算法的一种泛化。

 >> td.sorencen('tversky similarity'.split(), "similarity tversky tversky".split())
 0.8
 >> tversky = td.Tversky(ks=(0.5, 0.5))
 >> tversky('tversky similarity'.split(), "similarity tversky tversky".split())
 0.8
 >> td.jaccard('tversky similarity'.split(), "similarity tversky tversky".split())
 0.67
 >> tversky = td.Tversky(ks=(1, 1))
 >> tversky('tversky similarity'.split(), "similarity tversky tversky".split())
 0.67
 >> tversky = td.Tversky(ks=(0.2, 0.8))
 >> tversky('tversky similarity'.split(), "similarity tversky tversky".split())
 0.74

Tversky基指数可以平衡集合中不同类型元素的重要性,使其适用于各种应用,如信息检索、数据挖掘和医学诊断。

4、重叠相似度

重叠系数又被称作Szymkiewicz-Simpson系数,是两个集合之间的一种简单相似度。它计算的是集合交集大小与较小集合大小的比例。重叠系数在处理二进制数据或元素的存在与否很重要的情况下特别有用。其公式如下:

这个简单的公式也意味着,如果一个集合是另一个集合的子集。

 >> td.overlap('overlap similarity'.split(), "similarity overlap overlap".split())
 1.0

5、余弦相似度

余弦相似度是一种广泛使用的相似度测量方法,用于量化多维空间中两个非零向量之间角度的余弦值。它通常用于比较文档、文本或其他高维数据点之间的相似度。余弦相似度捕捉向量的方向或取向,而不是它们的大小。

两个向量A和B之间的余弦相似度公式如下:

其中A.B表示向量A和B之间的点积,||A||表示向量A的欧几里得范数。

这种相似度测量结果的范围从-1(表示完全相反)到1(表示完全相同)。值为0表示正交或去相关,而介于两者之间的值表示不同程度的相似性或不相似性。

在文本匹配中,属性向量A和B通常表示文档的术语频率向量。余弦相似度作为一种机制,用于在比较时标准化文档长度。在信息检索的背景下,两个文档之间的余弦相似度范围在0到1之间,因为术语频率不能为负。即使使用TF-IDF权重,两个术语频率向量之间的角度也不会超过90°。

 >> td.cosine('cosine'.split(), "similarity".split())
 0
 >> td.cosine('cosine sim'.split(), "cosine sim sim".split())
 0.81

textdistance在计算余弦相似度时使用的方法与标准相似度不同。所以建议使用scikit-learn的余弦相似度计算,对于第二个示例,其结果为0.94:

A = [1, 1];B = [1, 2],所以A.B = 3,因此cos(θ) = 3/√(2*5) = 0.94。

6、N-gram相似度

N-gram比较算法是一种通过分析两个字符串中连续n个字符的子序列(称为n-gram)来衡量它们之间相似度的方法。N-gram本质上是从给定字符串中提取的长度为n的子字符串。这种算法常用于文本分析、自然语言处理和相似度比较任务。N-gram比较算法的过程包括以下步骤:

N-gram提取:将每个输入字符串分割成重叠的n个字符的序列。

计数N-gram:统计两个字符串中每个独特n-gram的出现次数。

计算相似度:比较两个字符串之间的n-gram计数,并计算相似度分数。相似度分数可以使用各种度量方法计算,常用的选项包括贾卡德相似度和余弦相似度。

让我们举一个例子,比较两个有拼写错误的单词:(trigrasm 和 trigrams)

 >> trigrams = {"tri", "rig", "igr", "gra", "ram", "ams"}
 >> trigrasm = {"tri", "rig", "igr", "gra", "ras", "asm"}
 # there are 8 unique grams in our example so
 # there are 4 shared words and 4 different ones
 >> result = 4/8
 0.5

N-gram比较对于各种与文本相关的任务非常有用,例如文档相似度分析、抄袭检测和机器翻译。它捕捉文本中的局部模式,并可以提供关于字符串结构相似性的洞察。选择n(n-gram的长度)可以影响比较的粒度和敏感性。但是当处理短字符串时,这种算法会失效,其缺点在于该算法对不同的grams给予了更多的重视,而不是共享的grams。

基于序列的算法

基于序列的算法更侧重于分析和比较整个序列,而不是像基于令牌的算法那样比较序列中的令牌。这些算法在处理DNA序列、蛋白质序列或自然语言句子时尤其有价值。这里有一些示例性的例子:

1、Ratcliff-Obershelp相似度

Ratcliff-Obershelp相似度或Gestalt模式匹配是一种字符串相似度测量方法,侧重于基于两个字符串之间的共同子字符串来找到相似性。它特别适用于比较具有相似结构但可能在细微修改、删除或插入方面有所不同的字符串。该算法根据两个字符串之间最长公共子字符串的长度分配相似度分数。

Ratcliff-Obershelp算法的工作方式如下:

找到最长公共子字符串(LCS),在两个输入字符串之间识别最长的公共子字符串。这是通过找到在两个字符串中以相同顺序出现的公共字符序列来完成的。

然后首先移除LCS部分,并在同一位置进行分割。这将字符串分割成两部分:一部分在公共部分的左边,另一部分在右边。然后取两个字符串的左部分,再次应用此过程以找到它们的LCS。同样的过程也适用于右部分。继续递归这个过程,直到任何分割部分小于一定的设定值。

最后使用前面提到的Sorensen-Dice公式计算相似度分数。这个分数是共享字符数的两倍,除以两个字符串中的总字符数。

下面通过比较“RO pattern matching”和“RO practice”来清晰地解释这个算法。

共同的子字符串是“RO p”(4个字符)、‘a’(1个字符)、‘t’(1个字符)、‘e’(1个字符)。这意味着相似度为2*(4+1+1+1)/(19 + 11)=0.467。

但是这个算法有两个致命的缺点,第一个是它的复杂性,为O(n³),另一个是该算法不是可交换的,这意味着D(X, Y) != D(Y, X)。

对于第二个问题,我们来验证一下,第一个例子我们有D(“RO pattern matching”, “RO practice”)。让我们计算另一种方式:

 >> s1, s2 = "RO PATTERN MATCHING", "RO PRACTICE"
 >> td.ratcliff_obershelp(s1, s2), td.ratcliff_obershelp(s2, s1), len(s1), len(s2)
 (0.46, 0.53, 19, 11)

共同的子字符串是“RO p”(4个字符)、‘r’(1个字符)、‘a’(1个字符)、‘c’(1个字符)、‘i’(1个字符)。这意味着相似度为2*(4+1+1+1+1)/(19 + 11)=0.53。

这个例子展示了Ratcliff-Obershelp算法不可交换性的特点,即从不同的方向比较相同的字符串对可能得到不同的相似度分数。这一性质在需要对称相似度的应用中可能是一个限制。

2、最长公共子字符串/子序列相似度

最长公共子字符串算法是一种字符串相似度算法,专注于找出两个字符串之间的最长公共子字符串。它通过识别两个字符串共享的最长连续字符序列来衡量字符串之间的相似度。相似度得分可以通过将最长公共子字符串的长度除以最长字符串的长度来计算。

与子字符串不同,子序列不要求在原始序列中占据连续位置。因此,最长公共子序列总是大于最长公共子字符串。相似度得分的计算方式与后者相同。

以下示例:

 >> s1, s2 = "RO PATTERN MATCHING", "RO PRACTICE"
 >> td.lcsstr(s1, s2), td.lcsseq(s2, s1), td.lcsseq(s2, s1)
 ('RO P', 'RO PRATC', 'RO PRACI')
 >> td.lcsstr.normalized_similarity(s1, s2), td.lcsseq.normalized_similarity(s1, s2)
 (0.21, 0.42)

在上述示例中可以看到最长公共子字符串总是具有连续字符的子字符串,但在最长公共子序列中没有这个约束。

(A, B)的最长公共子序列与(B, A)不同。实际上可以在上面的例子中看到不同的结果(RO PRATC)和(RO PRACI)。

总结

在本文中,我们深入探讨了三个基本算法类别:基于编辑的算法、基于令牌的算法和基于序列的算法。需要记住的重要点是:

基于编辑的算法:

  • Damerau-Levenshtein和Jaro winkler距离通过编辑操作量化字符级相似度。
  • 适合强调单字符更改和更正的应用。
  • 对于拼写检查、光学字符识别、字符精确度和文本自动纠正非常有价值。

基于令牌的算法:

  • Jaccard 和Sørensen-Dice相似度关注令牌集,忽略序列。
  • 对于文档聚类、抄袭检测和推荐系统有效。
  • 强调存在而非顺序,有助于分类。
  • 可用于内容分类和文档比较。

基于序列的算法:

  • 最长公共子序列(LCS)和Ratcliff/Obershelp方法保留顺序。
  • 对于DNA序列对齐、文本近重复检测和版本控制至关重要。
  • 提供字符串内部结构关系的洞察。

没有单一的方法适用于所有情景,每一类算法都有其优势,适应特定的需求和背景。所以我们总结了这些算法,一个具备这些多样化技术知识的优秀数据科学家可以利用它们的综合力量来解决字符串相似度分析中的广泛挑战。

作者:Yassine EL KHAL

https://avoid.overfit.cn/post/43c11a3fee684fecb81eebf5647159aa

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/770286.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无法定位程序输入点…于动态链接库…的解决方法

如下图所示: 出现上述问题,主要是因为使用的动态库问题,具体就是电脑里有几个不同版本的osgEarth的动态库。如下图所示,本人电脑里编译了好几个版本的osgEarth库,并且把其中的两个加入到了环境变量中,导致出现上述错误: 程序使用的是绿框所示的D:\OSGCore\OSGEarth\bin …

哈喽GPT-4o,对GPT-4o 论文速写的思考与探索

作为一款强大的语言模型,ChatGPT 在论文写作上具备显著优势。它能够辅助学者或研究人员自动创建论文框架、摘要、文献综述及论文段落(如引言、方法、结果、结论等)。此外,ChatGPT 还能优化论文结构、润色、降低内容重复率&#xf…

redis-cluster(集群模式搭建)

redis中间件版本: redis-5.0.5环境介绍 这里使用服务器数量3,分别为172.0.0.1,172.0.0.2,172.0.0.3,每台机器redis节点数量2个,共6个redis节点构成redis-cluster模式。编译安装包 在172.0.0.1的机器上进入安装目录 cd …

AI大模型从入门到精通:一站式学习教程

前言 在聊到AI的时候,我们都离不开“大模型”这三个字。 AI大模型已经完全融入了各个领域,也融入了我们的生活,它好像无所不在、无所不能。 百度李彦宏说 :大模型改变世界; 360周鸿祎说:大模型是新时代“…

Frida案例-hook app中指定类的方法

界面如下 代码如下 点击‘点赞’按钮时,会触发getThumbsCount()函数 当前期望能通过frida获取getThumbsCount()的值 首先查看手机上正在运行的进程 frida-ps -U 进程不一定会以包名显示,还可能会以app的名…

基于主流SpringBoot进行JavaWeb开发的学习路线

目录 一、学习路线 (1)第一部分(Web前端开发的技术栈) (2)第二部分(Web后端开发) 二、学习之后必备的技能 三、学习Web开发的基础与未来的收获 学完这一类知识目标:…

vxe-table的序号一样

使用vxe-table的时候,有的时候会出现序号相同的现象,这种现象一般出现在我们后面自己添加的行中,就像这种 此时的这三个序号是相同的,我来说一下原因,这是在添加新的一行的时候,有的时候数据很多&#xff0…

理解MySQL核心技术:外键(Foreign Key)的设计与实现

在日常开发中,数据库是必不可少的部分,而MySQL作为最流行的关系型数据库之一,广泛应用于各类项目中。为了确保数据的完整性和一致性,外键(Foreign Key)无疑是一个重要的概念。在本篇文章中,我们…

认识100种电路之降压电路

在电子电路的世界里,降压电路扮演着至关重要的角色。 【为什么电路需要降压电路】 首先,我们要明白,不同的电子设备和元件往往需要特定的电压来正常工作。比如,某些芯片可能需要 5V 的电压,而我们提供的电源可能是 12…

zabbix报警机制,主动监控

zabbix思路流程 主动监控 默认zabbix使用的是被动监控,主被动监控都是针对被监控主机而言的。被动监控:Server向Agent发起请求,索取监控数据。此种模式常用主动监控:Agent向Server发起连接,向Server汇报 配置web2使用…

实验五 数据库完整性约束的实现与验证

题目 在实验四的基础上,重新创建以下三个表: 会员表:member(memno,memname,address,telephone,username,userpwd),主码为memno,属性memname不能取空值 员工表:employee(empno,empname,depno,sex,telephone…

Go语言工程管理

本文内容为Go工程创建和配置开发及简单程序示例。 目录 工程管理 GOPATH 配置GOPATH GOROOT 新建系统变量 配置go工程 添加go path 简单的程序实现 程序代码 开始运行 运行结果 内容解析 总结 工程管理 GOPATH go语言的项目,需要有特定的目录结构进行…

ArmPiPro-环境变量

V0.0 2024-07-04 V0.1 加入开发环境和PI4关于ROS的环境变量的对比 1.我们可以用env | grep ROS来查看Pi4中的ROS环境变量 如下图所示,不理解的,抛给AI快速了解一下。 2.ArmPiPro安装的ROS是ROS1-melodic 3.在开发时,需要在笔记本电脑上开一…

visual studio远程调试

场景一(被远程调试的电脑) 确定系统位数 我这里是x64的 找到msvsmon.exe msvsmon.exe目录位置解释: “F:\App\VisualStudio\an\Common7\IDE\”是visual studio所在位置、 “Remote Debugger\”是固定位置、 “x64”是系统位数。 拼起来就是…

uni-app上传失败超出文件限制解决方法-分包处理-预加载

分包背景 当你的上传出现一下错误: Error: 系统错误,错误码:80051,source size 2089KB exceed max limit 2MB [20240703 10:53:06][wxbf93dfb6cb3eb8af] [1.06.2405010][win32-x64] 说明你主包太大需要处理了,一下两种方法可以…

【LeetCode:841. 钥匙和房间 + DFS】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

嵌入式Linux系统编程 — 6.4 信号集

目录​​​​​​​ 1 信号集概念 2 sigemptyset、sigfillset初始化信号集 3 sigaddset、sigdelset向信号集中添加/删除信号 4 sigismember函数测试信号是否在信号集中 1 信号集概念 在Linux系统中,信号集(signal set)用于表示一组信号…

001:开源交易系统开发实战开篇

本专栏采用融入【主力思维】的方法学,包含数据抓取、特征模型开发、历史验证回归测试、每日动态风险评估管理等技术,较大的增强股票投资胜率,让IT开发者拥有一套实用的属于自己思路的专用交易软件。 先简要介绍下系统运行的成果和项目架构&a…

java版本ERP管理系统源码 Spring Cloud ERP_ERP系统_erp软件_ERP管理系统

在当今数字化时代,企业对高效、稳定且易于扩展的管理系统的需求日益增长。为了满足这一需求,我们精心打造了一款基于Java技术的ERP(Enterprise Resource Planning)管理系统。该系统充分利用了Spring Cloud Alibaba、Spring Boot、…

基于Java中的SSM框架实现小型企业人事管理系统项目【项目源码+论文说明】

基于Java中的SSM框架实现小型企业人事管理系统演示 摘要 人才是企业发展的核心力量,所以人事管理是企业管理中一项重要的任务。传统的人事管理系统不仅效率慢而且极易出错,使管理者不能清楚的了解每一位员工的详细情况,对企业的发展形成了不…