【NLP】KMP匹配算法

news2025/2/26 0:28:55

一、说明

      KMP算法。也称为Knuth-Morris-Pratt字符串查找算法可在一个字符串S内查找一个词W的出现位置。一个词在不匹配时本身就包含足够的信息来确定下一个匹配可能的开始位置,此算法利用这一特性以避免重新检查先前配对的字符。将时间复杂度从O(M*N)降为O(N).

        这个算法由高德纳和沃恩·普拉特在1974年构思,同年詹姆斯·H·莫里斯也独立地设计出该算法,最终三人于1977年联合发表。

二、不使用KMP算法查找过程描述

        我们将从S字符串中,查找P字段的位置。为了方便,我们将S叫做【文本】,将P叫做【模式】,整个查询过程如下图所示:

图1 从文本中查找字段的暴力查询

从以上查询中,我们不难看出,有许多多余的查询操作是不必要的。举例如下:

        既然ABC是匹配的,那么字段p的首字A与BCD重复地做了三次比较,而这三次比较的结果完全可以不依赖文本S的信息,单从P的内部就可以预测,A与{BCD}比较,其比较一定不匹配。因此,这三次比较多余。

三、如何提高搜索比较的效率

3.1 当字段内部无内部匹配的搜索

        什么叫“字段内无内部匹配”?就是字段p内无重复的字符。

        字段内没有重复的字符如p=【ABCDE】,与文本s匹配,这里假定文本是【ABCDABCABCABABCABCDA】,其匹配过程如下:

         显然,当出现前缀ABCD匹配,而到E的时候不匹配,p可以立刻跳到E当前的位置,将继续实行匹配。因为有前提“字段内无内部匹配”,因此,A后面没有A存在,也就无需匹配。

3.2 当字段内部有内部匹配的搜索

将以上的字段进行改变,p=【ABCAE】重复上面操作,效果图如下:

        可以看到,当E出现不匹配的时候,比较明智的跳转方法是,下次匹配发生在E的前一个位置,因为这里的A与字段首部存在一个匹配。

        直观地看出,要想去除不必要的匹配,有必要研究不匹配E前边的前缀字段。

四、前缀表的构想

        对于能否减少匹配的时间,关键要对模式进行研究。对于模式而言,其内部匹配决定了匹配模式如何移动。前人对于模式的研究,我们产生了前缀表这样的数据结构。本节我们试图应用一个前缀表,至于它如何构造,在后文中揭示。

        假定我们有如下字符模式:

 将以上模式做成如下表格,

模式的前缀表
i0123456
W[i]ABCDABD
T[i]-1000012

        朋友们可能不知道如何使用这个表格,那么我们将演示如何应用这个表格。

1)当第一个字符就不匹配怎么办?

        上图显然R-A不匹配,模式将移到下一个字符继续匹配,也就是模式的“-1”位置对齐到R的位置,继续下一轮匹配。  

        继续以后,S-A也不匹配,模式继续右移动...总之,所有的与模式第一个字符不匹配,就让模式的-1位置对齐,从模式的“0”位置继续匹配。这就是A对应-1的意义。

2)当第二个字符不匹配怎么办?

        当第一个字符匹配成功后,如何进行呢?继续下一个字符的匹配。如下图:

        第三个字符不匹配,如何继续?同样,将首段(0序号)移到该位置继续匹配。

        

 以此类推,表格中的  BCDA如果不匹配,都一样处理。

 3)当第六个字符不匹配怎么办?

 

  4)当第七个字符不匹配怎么办?

 

五、前缀表的构建法

5.1 前缀表构建原则

构建前缀表遵守下列原则:

  1.   只考虑模式内部结构,不考虑文本的结构。
  2.   只考虑模式中,哪一位字符不匹配,对于匹配的情况不考虑。
  3.   当模式第i位发生不匹配时,从[0, i-1] 位字段分析
  4.   对于【0,i-1】位字段,看其最大首尾匹配列,最大首尾匹配长度,正是前缀表的偏移T(i)

什么是最大首尾匹配?

就是形如:

 

 5.2 实现一个具体例子

        因此,构造前缀表的依据如图所示:

六、前缀表代码实现

        提供一组KMP的实现算法,请大家自行测试:

# Python program for KMP Algorithm
def KMPSearch(pat, txt):
	M = len(pat)
	N = len(txt)

	# create lps[] that will hold the longest prefix suffix
	# values for pattern
	lps = [0]*M
	j = 0 # index for pat[]

	# Preprocess the pattern (calculate lps[] array)
	computeLPSArray(pat, M, lps)

	i = 0 # index for txt[]
	while i < N:
		if pat[j] == txt[i]:
			i += 1
			j += 1

		if j == M:
			print ("Found pattern at index", str(i-j))
			j = lps[j-1]

		# mismatch after j matches
		elif i < N and pat[j] != txt[i]:
			# Do not match lps[0..lps[j-1]] characters,
			# they will match anyway
			if j != 0:
				j = lps[j-1]
			else:
				i += 1

def computeLPSArray(pat, M, lps):
	len = 0 # length of the previous longest prefix suffix

	lps[0] # lps[0] is always 0
	i = 1

	# the loop calculates lps[i] for i = 1 to M-1
	while i < M:
		if pat[i]== pat[len]:
			len += 1
			lps[i] = len
			i += 1
		else:
			# This is tricky. Consider the example.
			# AAACAAAA and i = 7. The idea is similar
			# to search step.
			if len != 0:
				len = lps[len-1]

				# Also, note that we do not increment i here
			else:
				lps[i] = 0
				i += 1

txt = "ABABDABACDABABCABAB"
pat = "ABABCABAB"
KMPSearch(pat, txt)

# This code is contributed by Bhavya Jain

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ Primer Plus 第三章习题

目录 复习题 1. 为什么C有多种整型&#xff1f; 2. 声明与下述描述相符的变量&#xff1f; 3. C 提供了什么措施来防止超出整型的范围&#xff1f; 4. 33L和33之间有什么区别&#xff1f; 5. 下面两条C语句是否等价&#xff1f; 6. 如何使用C来找出编码88表示的字符&…

又一个生物标志物ADMA被发现!可为OA治疗提供新方向!

文章标题&#xff1a;Metabolite asymmetric dimethylarginine (ADMA) functions as a destabilization enhancer of SOX9 mediated by DDAH1 in osteoarthriti 发表期刊&#xff1a;Science Advances 影响因子&#xff1a;14.95 作者单位&#xff1a;浙江大学医学院附属邵逸…

EasyUi03

1.无限极分类. 1.1无限极分类介绍. 1.1.1何为无限极分类. 无限极分类简单点说就是一个类别能够分多个子类&#xff0c;而后一个子类又能够分多个子类&#xff0c;就这样无限分下去&#xff0c;就好象 windows能够新建一个文件夹&#xff0c;而后在这个文件夹里又能够建一些文…

《嵌入式系统》知识总结12:SysTick定时器

SysTick定时器 系统时钟&#xff08;SysTick&#xff09; Corte-M3在内核中包含的简单定时器 • 该定时器的时钟源可以来自CM3内部时钟&#xff08;FCLK&#xff09;&#xff0c;或CM3外部时钟&#xff08;STCLK&#xff09; • 在STM32微控制器中&#xff0c;SysTick的时钟源可…

平板触控笔哪款好用?电容笔牌子排行

现如今&#xff0c;电容笔越来越受欢迎&#xff0c;不少人在记笔记、学画画甚至是玩游戏的时候都会使用它。最近看到很多人问&#xff0c;iPad电容笔哪款好用&#xff1f;针对这个问题&#xff0c;我来给大家推荐四款公认好用的平替电容笔&#xff0c;一起来看看吧。 一、主动…

实验篇(7.2) 08. 通过安全隧道访问内网服务器 (FortiClient-IPsec) ❀ 远程访问

【简介】通过对SSL VPN与IPsec VPN的对比&#xff0c;我们知道SSL VPN是基于应用层的VPN&#xff0c;而IPsec VPN是基于网络层的VPN&#xff0c;IPsec VPN对所有的IP应用均透明。我们看看怎么用FortiClient实现IPsec VPN远程访问。 实验要求与环境 OldMei集团深圳总部部署了一台…

眼底图片解读(对比图!!!)

目录 1. 前言 2.常见眼底解析 (1) 黄斑变性 (2) 糖尿病视网膜病变 (3) 青光眼 (4) 视网膜血管阻塞 (5)视网膜裂孔和脱离 1. 前言 眼底图像是通过眼底摄影等技术获取的眼底部位的影像&#xff0c;可以提供关于眼睛健康和疾病的重要信息。以下是眼底图像中常见的信息和相关…

只见新人笑,不见旧人哭 ChatGPT淘汰了多少产品?快来了解!

ChatGPT作为目前世界上最先进的人工智能聊天工具&#xff0c;其GPT模型就是一种自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;使用多层变换器&#xff08;Transformer&#xff09;来预测下一个单词的概率分布&#xff0c;通过训练在大型文本语料库上学习到的语言模…

chatgpt赋能python:Python自动运行教程:让你的工作更智能化

Python自动运行教程&#xff1a;让你的工作更智能化 Python是一种高级、解释型、面向对象的编程语言&#xff0c;被广泛应用于数据分析、机器学习和自动化任务等领域。除此之外&#xff0c;Python还能够实现自动化运行&#xff0c;让用户无需手动干预&#xff0c;从而减轻工作…

Think系列产品进入BIOS的操作方法

Think系列产品进入BIOS的操作方法&#xff1a; 适用范围&#xff1a;ThinkPad全系列笔记本ThinkCentre全系列一体机ThinkStation全系列工作站 温馨提示&#xff1a;如果您用的是Win8/8.1系统&#xff0c;小乐强烈建议您在系统下执行“重启”后的开机界面(切记&#xff1a;不是从…

DynaMask:用于实例分割的动态掩码选择

文章目录 DynaMask: Dynamic Mask Selection for Instance Segmentation摘要本文方法Dual-Level FPNRegion-Level FPNFeature Aggregation Module (FAM)Mask Switch Module (MSM)损失函数 实验结果 DynaMask: Dynamic Mask Selection for Instance Segmentation 摘要 具有代表…

共见·价值成就|光环云与您相约2023亚马逊云科技合作伙伴峰会!

在云计算蓬勃发展的今天&#xff0c; 在推动业务发展、实现共赢的过程中&#xff0c; 价值成就&#xff0c;是亚马逊云科技对合作伙伴 自始至终的承诺。 为助力合作伙伴成就价值&#xff0c;共建成长路径&#xff0c; 2023亚马逊云科技合作伙伴峰会将于 6月27日在上海世博…

跟着LearnOpenGL学习7--坐标系统

文章目录 一、概述二、变换过程三、局部空间四、世界空间五、观察空间六、裁剪空间6.1、正射投影6.2、透视投影 七、组合变换八、3D实战8.1、创建模型矩阵8.2、创建观察矩阵8.3、创建投影矩阵8.4、变换矩阵传入着色器 九、3D立方体9.1、Z缓冲9.2、更多的立方体 一、概述 OpenG…

【022】C++的结构体、共用体以及枚举详解(最全讲解)

C的结构体、共用体以及枚举详解 引言一、结构体的概述二、结构体变量的操作2.1、结构体变量的初始化2.2、清空整个结构体变量2.3、键盘给结构体变量中的成员赋值2.4、单独操作结构体中的成员2.5、相同类型结构体变量之间的赋值 三、结构体嵌套结构体四、结构体数组五、结构体指…

JUC基础-0531

3 线程间通信 线程间通信的模型有两种:共享内存和消息传递&#xff0c;以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析 多线程编程步骤&#xff1a; 第一步&#xff1a;创建资源类&#xff0c;在资源类创建属性和操作方法第二步&#xff1a;在资源…

电脑录音软件哪个好用?如何录制声音?

案例&#xff1a;有没有好用的电脑录音软件分享&#xff1f; 【使用手机录制电脑上的声音&#xff0c;会录入外界的杂音&#xff0c;导致录音文件质量不佳。我需要一款支持录制电脑声音的软件&#xff0c;小伙伴们有没有好用的电脑录音软件推荐&#xff1f;】 电脑录音软件成…

docker安装RabbitMQ教程(2023年最详细)

1.使用docker查询rabbitmq的镜像 docker search rabbitmq 2.安装镜像 如果需要安装其他版本在rabbitmq后面跟上版本号即可 docker pull rabbitmq:3.7.7-management 说明 docker pull rabbitmq:版本号 -management 安装name为rabbitmq的这里是直接安装最新的 docker pull …

算法leetcode|54. 螺旋矩阵(rust重拳出击)

文章目录 54. 螺旋矩阵&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a;每次循环移动一步&#xff1a;每次循环完成一个顺时针&#xff1a…

玩转 GPT4All

目录 什么是Chatgpt 什么是gpt4all 如何使用 第一步&#xff1a;下载LLM模型 第二步&#xff1a;下载代码 第三步&#xff1a;将模型替换到 第四步&#xff1a;执行启动命令 第五步&#xff1a;生成自己的客户端 第六步&#xff1a;启动 第七步&#xff1a;配置UI 什么…

【CesiumJS入门】(3)ImageryLayer之图层卷帘

前言 上一篇博客简单得介绍了影像图层并成功在视图上加载出来了&#xff0c;而今天我们来实现一个简单的可视化效果&#xff0c;影像图层卷帘。 前置知识&#xff1a;Cesium 事件详解&#xff08;鼠标事件、相机事件、键盘事件、场景触发事件&#xff09;_cesium点击事件_GIS…