KMP总结

本文深入浅出地介绍了KMP算法的原理与应用,通过实例详细解释了如何利用KMP算法进行字符串匹配,避免传统暴力匹配的缺陷。

推荐博客:http://www.cnblogs.com/SYCstudio/p/7194315.html

哇塞!只想说如果没有静下心,头脑不清晰的时候来看KMP真的很醉,昨天下午队伍确定分工后,我负责字符串,处理字符串怎么能不了解KMP算法呢,于是乎,从昨天下午开始到写博客的前两分钟,苦逼的我一直在啃KMP,让人心力交瘁啊,虽然之前数据结构课的时候有看到KMP但是因为老师没有讲,其实自己当时有试着去了解,但是那时候真的看得很吃亏,导致无果,这次重振旗鼓真的打算好好了解一番。在网上搜了很多资料,但是由于每个人有每个人不同的理解和思考方式,所以刚开始的时候简直就是脑袋都要炸了,但是皇天不负有心人,在看了n篇大佬的博客之后,再加上自己手动模拟终于弄清楚了,在看博客的过程中,有看到一位博主说如果你学到的知识不能用自己的话、自己的方法总结出来的话那么你很快就会忘记,学到也只能算是暂时的了解,所以在懂了KMP之后,鼓起很大的勇气决定来消化一下KMP。KMP是由研究出此算法的三位大佬名字的首字母来命名的(Knuth,Morris,Pratt)。最初的最初遇到字符串匹配的题目只知道一昧地模拟,暴解,每次匹配失败都会放弃已经匹配的信息,将模式串往后移一位继续比较,这样的时间复杂度是很高的,很容易超时,而KMP则充分利用了匹配失败前字符串的匹配程度来最大程度地移动字符串又不会漏掉。

例子:(从大佬那里借来用用,hhh)

原串S="abaabaabbabaaabaabbabaab"

模式串P="abaabbabaab"

最开始

    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

1  a  b  a  a  b  a  a  b  b  a  b   a   a  a   b   a   a   b   b   a   b  a   a   b

    a  b  a  a  b  b  a  b  a  a  b

                                                 

2  a  b  a  a  b  a  a  b  b  a  b   a   a   a   b   a   a   b   b   a   b  a   a   b

                a  b  a  a  b  b  a  b   a   a   b     

                                                          

3  a  b  a  a  b  a  a  b  b  a  b   a   a   a   b   a   a   b   b   a   b  a   a   b

                                        a  b   a   a  b   b   a   b   a   a   b      

                                                           

4  a  b  a  a  b  a  a  b  b  a  b   a   a   a   b   a   a   b   b   a   b  a   a   b 

                                                      a   b   a   a   b   b   a   b   a   a   b 

                                                           

5  a  b  a  a  b  a  a  b  b  a  b   a   a   a   b   a   a   b   b   a   b  a   a   b   

                                                           a   b   a   a   b   b   a   b  a   a   b                                                                                                                                                                                     

第一次匹配时在下标为5的地方匹配失败,前面5个字符已经是匹配的了,如果按照常规的暴力法是将P[0]移动到与S[1]继续比较,这样的话就浪费了匹配失败前已经匹配的资源了,相信看到这个匹配跟移动过程算是初步地了解了,现在我们需要从每个匹配失败的位置知道应该怎么移动字符串。于是就大佬们就相出了一个神奇的办法,也就是初始化记录模式串每个字符之前的相同前缀后缀的最大长度,算法导论中定义为next数组。设置第一个字符next[0]=-1,接下来第i个字符,如果P[i]=P[next[i-1]+1],那么next[i]=next[i-1]+1,否则回溯到next[next[i-1]],将P[i]与P[next[next[i-1]]+1]继续比较,因为在计算next[i]之前已经计算好了next[0...i-1],当P[i]=P[next[i-1]+1]时,因为可以确定的是

P[0....next[i-1]]=P[i-1-next[i-1]...next[i-1]],所以如果P[i]=P[next[i-1]+1],那么就有

P[0....next[i]]=P[i-1-next[i-1]...-next[i]],所以next[i]=next[i-1]+1,回溯得到的next[i]也是一样的道理,如果不存在前缀和后缀相等,那么next[i]=-1。


### KMP算法详解 KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,用于在一个主串中快速找到模式串的位置。其核心思想在于通过预处理模式串构建部分匹配表(Partial Match Table, PMT),从而减少不必要的字符比较次数。 #### 部分匹配表的计算 部分匹配表记录了模式串前缀和后缀的最大重叠长度。具体来说,对于模式串 `P` 的每个位置 `i`,计算最长相等前后缀的长度并存入数组 `next[i]` 中[^1]。 以下是部分匹配表的构造方法: ```python def compute_next(pattern): n = len(pattern) next_array = [0] * n # 初始化 next 数组 j = 0 # 前缀指针 for i in range(1, n): # 后缀指针从第二个字符开始遍历 while j > 0 and pattern[j] != pattern[i]: j = next_array[j - 1] if pattern[j] == pattern[i]: j += 1 next_array[i] = j # 记录当前最大公共前后缀长度 return next_array ``` #### 字符串匹配过程 基于已构建的部分匹配表,可以高效完成字符串匹配操作。当遇到失配时,无需回退主串指针,而是依据部分匹配表调整模式串起始位置继续匹配。 下面是完整的 KMP 算法实现: ```python def kmp_search(text, pattern): m = len(text) n = len(pattern) next_array = compute_next(pattern) # 构建部分匹配表 matches = [] j = 0 # 模式串索引 for i in range(m): # 主串索引 while j > 0 and text[i] != pattern[j]: j = next_array[j - 1] if text[i] == pattern[j]: j += 1 if j == n: # 找到匹配子串 matches.append(i - n + 1) j = next_array[j - 1] # 继续寻找下一个可能的匹配 return matches ``` --- ### KMP算法在OFDM中的应用 正交频分复用(Orthogonal Frequency Division Multiplexing, OFDM)是一种广泛应用于现代通信系统的调制技术。它将信道划分为多个相互正交的子载波,在这些子载波上传输数据。为了提高传输效率和抗干扰能力,OFDM通常会引入同步机制以及训练序列来辅助接收端解码。 KMP算法可以在以下几个方面与OFDM相结合: #### 1. **训练序列检测** 在OFDM系统中,发送端会在帧头插入特定的训练序列以便于接收端进行同步和信道估计。由于训练序列具有固定的结构特征,因此可以通过KMP算法快速定位该序列在接收到的数据流中的位置[^2]。 例如,假设训练序列为 `"ABCD"`,而接收到的一段信号表示为一维采样值 `[..., A', B', C', D', ...]`,则可将其离散化后再运用KMP算法执行精确匹配。 #### 2. **符号边界识别** 除了训练序列外,某些标准还规定了特殊的标志位用来指示每一段有效负载的起点和终点。同样地,借助KMP算法能够迅速发现这些标记所在的具体时间戳,进而帮助解析后续的信息字段。 #### 3. **错误校验码验证** 一些高级纠错编码方案可能会附加冗余比特作为检错手段之一;如果采用固定形式的循环冗余检验 (CRC),那么也可以考虑利用类似的思路去加速查找对应的结果片段。 尽管如此,值得注意的是实际工程实践中往往更倾向于硬件电路或者专用指令集处理器来达成同样的目标,因为它们具备更高的实时性和更低功耗特性。 --- ### 总结 综上所述,虽然理论上存在多种方式让经典计算机科学理论融入无线通讯领域之中,但在真实场景下仍需综合考量性能指标等因素做出合理取舍。无论如何,深入理解基础原理始终有助于启发创新解决方案的设计灵感!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值