首页 > 编程语言 >寻根KMP算法

寻根KMP算法

时间:2024-05-04 19:56:30浏览次数:19  
标签:相等 匹配 后缀 寻根 next 算法 KMP

本人被\(KMP\)已经折磨许久。五战KMP。方知之前理解确实浅。故写此篇。
这是之前那篇,实在是太浅,不过对代码做了注释。https://www.acwing.com/solution/content/131255/


本篇重点说明\(KMP\)的原理,而非过程。过程相信其他博客已经写的十分完善了。

\(KMP\) 算法(\(Knuth-Morris-Pratt\) 算法)是一个著名的字符串匹配算法,效率很高,但是确实有点复杂。

暴力及举例可以去看别的博客。本处不赘述。

匹配

观察暴力,相信也知道,每次我们漏掉了些信息。什么信息呢?

假设当前到这就匹配不成功了。

暴力做法:

直接从头开始匹配。
假设移动如这样:

不断向右移动。。。发现了什么?
好像能不能匹配和最上面串没关系吧。由于前半段已经匹配啦,上面等于下面)
更准确的讲,是不是只跟串的前后缀有关系。
因此,我们考虑至少向后移动到什么位置可以继续匹配上面绿圈
假设到这。

黄色部分相等。至少移动多少呢?就是使前后缀相等的最大长度。(前后缀不等无法匹配, 又因为至少)

假设我们当前已经求出这个东西。叫做next。
那就容易了。如果蓝圈红圈不匹配,考虑回退,那就回退到next就行了。中间隔下的一定不行,我们知道前后缀不等的,那么一定没法匹配。如果next不行,那就重复这个过程。

代码

\(Next\)

求使前后缀相等的最大长度。略变一下。
强调一下:\(next[i]\) 存储的就是使子串 s[0…i] 有最长相等前后缀的前缀的最后一位的下标。
\(next\) 数组的含义就是当 j + 1 位失配时,j 应该回退到的位置。

首先,假设现在j在的位置是\(next[i - 1]\)的位置,next[1 ~ i-1]已经求出。
观察\(next[i]\)的性质:

  1. 使1~i前后缀相等的最大长度 <= 1~ i-1前后缀相等的最大长度+1。这是因为你可以画一下图,如果更大,那就一定不等(1~i-1前后缀已最大),最多扩展i,j+1嘛。
  2. 其实还是和匹配一样了吧。next[i]肯定要在带上i==j+1的前后缀相等的长度 取最大, 按照暴力思路,你当然会从大到小枚举所有前后缀长度,取第一个行的。实质就是不断右移的过程。
    当si!=sj+1时,考虑后退,这个时候又在向右移动了。使前后缀相等,那么回退取值一定只有j,next[j],next[next[j]]....
    这是因为你可以任取不在其中的一个数k,那么前后缀就不等了,根本没法匹配。(根据next定义,不在这些不断“最大前后缀相等长度”中,那肯定不等啊)

匹配成功后,j=next[i],重复上述过程。可不就求出来了?

好了那这样就愉快解决了。

\(PS:实在看不懂,字符串哈希也行啊()\)

标签:相等,匹配,后缀,寻根,next,算法,KMP
From: https://www.cnblogs.com/qinyiting/p/17870833.html

相关文章

  • 常见的排序算法
    常见的排序算法目录一、冒泡排序(BubbleSort)二、插入排序(InsertSort)三、选择排序(SelectionSort)四、希尔排序(ShellSort)五、快速排序(QuickSort)六、堆排序(HeapSort)七、归并排序(MergeSort)八、计数排序(CountSort()九、桶排序(BucketSort)十、基数排序(RadixSor......
  • 算法随笔——主席树(可持久化线段树)
    介绍主席树即可持久化线段树,由hjt大佬发明。好像又称函数式线段树。可以查询序列在任意时间的历史状态。学习链接学习链接主要思路维护历史状态,若采用直接拷贝整棵树的方式,空间爆炸。可以发现每次修改只有部分节点发生了改变(其实就是到树根那条链会改变),因此每次只需要记......
  • leetcod算法热题--移动零
    题目给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请注意,必须在不复制数组的情况下原地对数组进行操作。示例1:输入:nums=[0,1,0,3,12]输出:[1,3,12,0,0]示例2:输入:nums=[0]输出:[0]提示:1<=nums.length<=......
  • leetcode算法热题--最长连续序列
    题目给定一个未排序的整数数组nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为O(n)的算法解决此问题。示例1:输入:nums=[100,4,200,1,3,2]输出:4解释:最长数字连续序列是[1,2,3,4]。它的长度为4。示例2:输入:nums=......
  • 个人算法竞赛模板(2024.5.4)
    精简版:#include<algorithm>#include<cmath>#include<cstring>#include<iostream>#include<map>#include<queue>#include<set>#include<stack>#include<string>#include<vector>#include<......
  • 网友开放的开源项目:网页版的A*算法可视化演示程序
    相关项目:https://xueqiaoxu.me/#projects项目介绍:AJavaScriptpath-findinglibraryforgridbasedgames.Italsocomesalongwithaninteractivevisualizationofnumerousstrategies.项目地址:https://github.com/qiao/PathFinding.js演示地址:https://qia......
  • 算法随笔——manacher
    非常好学习资料manacher求最长回文子串暴力枚举回文中心\([1,n]\),暴力向两边拓展,然后\(checkmax\)。时间复杂度\(O(n^2)\)可以用二分哈希优化至\(O(n\logn)\)算法思路当求解第\(i\)个字符为回文中心的时候,已经知道了\([1,i-1]\)之间的信息。于是引入\(p[i]\):......
  • A* 算法、PathFinding问题中的 allow diagonal 和 don't cross corners,以及 .map文件
    地址:https://webdocs.cs.ualberta.ca/~nathanst/papers/benchmarks.pdf关于地图文件:.map文件的格式参考:https://movingai.com/benchmarks/formats.html......
  • Kosaraju 算法
    引入Kosaraju算法用于求解强连通分量,在稠密图下复杂度会比tarjan算法要优秀。(?过程对整个图进行搜索,并且将没一个顶点按照DFS序压入栈中。建一个反图。对于栈中的每一个点再反图上跑一遍DFS,现在跑出来的子图即为一个强连通分量。标记这几个点。重复执行操作......
  • m基于LDPC编译码的matlab误码率仿真,对比SP,MS,NMS以及OMS四种译码算法
    1.算法仿真效果matlab2022a仿真结果如下:    2.算法涉及理论知识概要       低密度奇偶校验码(LDPC)译码是现代通信系统中一种高效的错误校正技术,广泛应用于无线通信、卫星通信和数据存储等领域。LDPC码因其良好的纠错性能和接近香农极限的潜力而受到重视。本文......