字符串匹配的KMP算法

字符串匹配是计算机的基本任务之一。

举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"?

许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一,这种算法不太容易理解,网上有很多解释,但读起来都很费劲。直到读到Jake Boxer的文章,我才真正理解这种算法。下面,我用自己的语言,试图写一篇比较好懂的KMP算法解释。

1.首先,字符串"BBC ABCDABABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第一个字符,进行比较。因为B与A不匹配,所以搜索词后移一位。


2.因为B与A不匹配,搜索词再往后移。


3.就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止。


4.接着比较字符串和搜索词的下一个字符,还是相同。


5.直到字符串有一个字符,与搜索词对应的字符不相同为止。


6.这时,最自然的反应是,将搜索词整个后移一位,再从头逐个比较。这样做虽然可行,但是效率很差,因为你要把"搜索位置"移到已经比较过的位置,重比一遍。


7.一个基本事实是,当空格与D不匹配时,你其实知道前面六个字符是"ABCDAB"。KMP算法的想法是,设法利用这个已知信息,不要把"搜索位置"移回已经比较过的位置,继续把它向后移,这样就提高了效率。


8.怎么做到这一点呢?可以针对搜索词,算出一张《部分匹配表》(Partial Match Table)一般就是我们所说的next函数值。这张表是如何产生的,后面再介绍,这里只要会用就可以了。


9.已知空格与D不匹配时,前面六个字符"ABCDAB"是匹配的。


查表可知,最后一个匹配字符B对应的"部分匹配值"为2,因此按照下面的公式算出向后移动的位数:

  移动位数 = 已匹配的字符数 - 对应的部分匹配值

因为 6 - 2 等于4,所以将搜索词向后移动4位。

10.因为空格与C不匹配,搜索词还要继续往后移。这时,已匹配的字符数为2("AB"),对应的"部分匹配值"为0。所以,移动位数 = 2 - 0,结果为 2,于是将搜索词向后移2位。


11.因为空格与A不匹配,继续后移一位。


12.逐位比较,直到发现C与D不匹配。于是,移动位数 = 6 - 2,继续将搜索词向后移动4位。


13.逐位比较,直到搜索词的最后一位,发现完全匹配,于是搜索完成。如果还要继续搜索(即找出全部匹配),移动位数 = 7 - 0,再将搜索词向后移动7位,这里就不再重复了。


14.下面介绍《部分匹配表》是如何产生的。

首先,要了解两个概念:"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。


15."部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。


以"ABCDABD"为例,

  - "A"的前缀和后缀都为空集,共有元素的长度为0;

  - "AB"的前缀为[A],后缀为[B],共有元素的长度为0;

  - "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;

  - "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;

  - "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1;

  - "ABCDAB"的前缀为[A, AB, ABC, ABCD,ABCDA],后缀为[BCDAB, CDAB, DAB,AB, B],共有元素为"AB",长度为2;

  - "ABCDABD"的前缀为[A, AB, ABC, ABCD,ABCDA, ABCDAB],后缀为[BCDABD, CDABD,DABD, ABD, BD, D],共有元素的长度为0。

16."部分匹配"的实质是,有时候,字符串头部和尾部会有重复。比如,"ABCDAB"之中有两个"AB",那么它的"部分匹配值"就是2("AB"的长度)。搜索词移动的时候,第一个"AB"向后移动4位(字符串长度-部分匹配值),就可以来到第二个"AB"的位置。


(完)

内容概要:本文档详细介绍了基于MATLAB实现多目标差分进化(MODE)算法进行无人机三维路径规划的项目实例。项目旨在提升无人机在复杂三维环境中路径规划的精度、实时性、多目标协调处理能力、障碍物避让能力和路径平滑性。通过引入多目标差分进化算法,项目解决了传统路径规划算法在动态环境和多目标优化中的不足,实现了路径长度、飞行安全距离、能耗等多个目标的协调优化。文档涵盖了环境建模、路径编码、多目标优化策略、障碍物检测与避让、路径平滑处理等关键技术模块,并提供了部分MATLAB代码示例。 适合人群:具备一定编程基础,对无人机路径规划和多目标优化算法感兴趣的科研人员、工程师和研究生。 使用场景及目标:①适用于无人机在军事侦察、环境监测、灾害救援、物流运输、城市管理等领域的三维路径规划;②通过多目标差分进化算法,优化路径长度、飞行安全距离、能耗等多目标,提升无人机任务执行效率和安全性;③解决动态环境变化、实时路径调整和复杂障碍物避让等问题。 其他说明:项目采用模块化设计,便于集成不同的优化目标和动态环境因素,支持后续算法升级与功能扩展。通过系统实现和仿真实验验证,项目不仅提升了理论研究的实用价值,还为无人机智能自主飞行提供了技术基础。文档提供了详细的代码示例,有助于读者深入理解和实践该项目。
### KMP字符串匹配算法的实现与原理 #### 原理概述 KMP算法的核心在于两个方面:部分匹配表(通常称为`next`数组)的构建以及如何利用这个表格来高效地完成字符串匹配[^1]。 #### 部分匹配表(next数组)的作用及其计算方式 为了提高查找效率,KMP引入了前缀函数的概念,即对于模式串P中的每一个位置i,next[i]代表的是从起始至第i位子串的最大相同真前缀和真后缀长度。当遇到不匹配情况时,可以根据此信息决定跳转到哪个位置继续尝试而不是盲目移动指针回到起点重新开始比较。具体来说,在初始化阶段就要先算好整个模式串对应的next值列表作为后续操作的基础依据[^3]。 #### 匹配流程描述 实际执行过程中,主串S和模式串P各自设有一个游标变量指向当前考察字符处。每当两者对应项一致,则同步前进一位;反之如果发现差异存在但又不是首次访问该节点的话(意味着已经有过至少一轮成功的局部对比),那么就依照预先准备好的next映射关系调整后者所指示的位置直至找到新的候选点或者确认完全失败为止。值得注意的是在整个扫描期间内针对源数据流里的任一成员都只会被检验过一次而已,因此整体性能得以保持在线性级别上运行[^5]。 ```python def compute_next(pattern): m = len(pattern) next_array = [-1] * m k = -1 for q in range(1, m): while k >= 0 and pattern[k + 1] != pattern[q]: k = next_array[k] if pattern[k + 1] == pattern[q]: k += 1 next_array[q] = k return next_array def kmp_search(text, pattern): n, m = len(text), len(pattern) if not text or not pattern or n < m: return -1 next_array = compute_next(pattern) i = j = 0 while i < n: if j == -1 or text[i] == pattern[j]: i += 1 j += 1 if j == m: return i - j else: j = next_array[j] return -1 if j != m else (i - j) if __name__ == "__main__": txt = "ABCDABC" pat = "BCD" index = kmp_search(txt, pat) print(f"Pattern found at index {index}" if index != -1 else "No match found.") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值