首页 > 编程语言 >KMP算法理解

KMP算法理解

时间:2023-01-11 23:34:02浏览次数:41  
标签:匹配 next 算法 理解 KMP 字符串 underline

KMP

我的理解 是一个通过预处理储存字符串自身具有的前后缀一致性质来达到快速处理“字符串匹配”“字符串重复”的问题的算法,
核心是 \(next\) 数组。

以字符串匹配为例子,简单阐述一下KMP算法相比于暴力算法的优越性。
举例问题是字符串 \(A\) 中有多少个字符串 \(B\);

在 \(abababaac\) 中找 \(ababab\)

假设已经处理到这种情况:
$ \ \ \ \ \ \ \ \ 1 \ 2 \ 3 \ 4 \ 5 \ 6 \ 7 \ 8 \ 9$
$A = a\ b\ \underline{a\ b \ a \ b \ a} \ a \ c $
\(B = \ \ \ \ \ \ \underline{a \ b \ a \ b \ a} \ b\)
假设是从A的第3位暴力处理到了第7位
现在要处理第8位,按照暴力算法的思路,由于第8位的字符对应不上,所以要将 \(B\) 的首位调到第4位重新去匹配
但是这其中可以优化,注意到 \(B\) 串中 \(ababa\) 的前缀 \(aba\) 和后缀 \(aba\) 相同,我可以直接把 \(B\) 串后移两位,变成如下情况继续匹配:
$ \ \ \ \ \ \ \ \ 1 \ 2 \ 3 \ 4 \ 5 \ 6 \ 7 \ 8 \ 9$
$A = a\ b \ a\ b \ \underline{a \ b \ a} \ a \ c $
\(B = \ \ \ \ \ \ \ \ \ \ \ \underline{a \ b \ a} \ b \ a \ b\)
这样子免去了暴力算法的又一次从头开始匹配,而如何让 \(B\) 去移动,就是KMP算法要处理的。(虽然这个例子优势不明显)

next数组

首先要明确这是对于字符串自身而言的性质

\(next[i]\) 表示的是字符串 \(S\) 的子串 \(S[1 … i]\) 中满足真前缀和真后缀相等的最长长度 \(len\) ,即满足\(S[1…len] = S[i - len + 1…i]\)的 \(len\) 的最大值
举个例子, \(abababc 的next[1] = 0,next[2] = 0, next[3] = 1,(a),next[4] = 2, (ab), next[5] = 3, (abc), next[6] = 4, (abcd), next[7] = 0\);

求法如下:
\(1.假设next[1]到next[i - 1]已经求出来; \\2.扩展匹配长度j,匹配失败时令j = next[j],直到j = 0; \\3.如果扩展成功,j++, next[i]=j。\)

void prenet(string a) {
  int n = strlen(a);
  for (int i = 2, j = 0; i <= n; ++i){
      while (a[i] != a[j + 1] && j > 0) j = net[j];
      if (a[i] == a[j + 1]) ++j;
      net[i] = j;
  }
}

附上一些容易想到的拓展点:
\(1.字符串匹配时可以直接把模式串放在待匹配串前面,\\中间用特殊字符隔开后(避免求next时匹配到超出模式串的字符)\\直接求next数组,那么next[i] = 模式串长度的,就是匹配成功的。\)
\(2.next[i],next[next[i]],next[next[next[i]]]等等都是位置i的可匹配长度,\\next[i]储存的是i位置的可匹配长度最大值,\\那么最小值也可以通过递推直到next[j]=0,j就是最小值\)

标签:匹配,next,算法,理解,KMP,字符串,underline
From: https://www.cnblogs.com/cancers/p/17045195.html

相关文章

  • m分集2跳OFDM系统中基于功率分配和子载波配对算法的信道容量matlab仿真
    1.算法描述       随着当代无线通信事业的迅猛发展,无线频谱资源已显得越来越匮乏,传统固定静态的无线频谱分配模式和策略,很难为未来的无线通信事业的进一步发展......
  • 算法学习笔记(55)——推公式
    推公式题目链接:AcWing125.耍杂技的牛先给出结论:按照W[i]+S[i]从小到大的顺序排,最大的危险系数一定是最小的。证明思路:贪心得到的答案\(\ge\)最优解贪心得到的答......
  • 算法学习笔记(54)——绝对值不等式
    绝对值不等式题目链接:AcWing104.货仓选址\[\begin{align*}f(x)&=\lvertx_1-x\rvert+\lvertx_2-x\rvert+\cdots+\lvertx_n-x\rvert\\&=(\lve......
  • foreign key不难理解嘛
    SQLiteForeignKeySupport 讲得挺清楚的啊。更短的例子:CREATETABLEperson(nameTEXTPRIMARYKEY,addrTEXT);INSERTINTOpersonVALUES('tom','somewhere');......
  • 深入理解AnnotatedBeanDefinitionReader
    AnnotatedBeanDefinitionReader是干什么的?从类对象中获取基本注解信息,创建BeanDefinition对象。将BeanDefinition对象注册到BeanDefinitionRegistry对象中。由于Bean......
  • 代码随想录算法训练营day01 | leetcode 704/27
    前言  考研结束半个月了,自己也简单休整了一波,估了一下分,应该能进复试,但还是感觉不够托底。不管怎样,要把代码能力和八股捡起来了,正好看到卡哥有这个算法训练营,遂果断参加......
  • 一致性哈希算法
    一个良好的分布式哈希方案,应该具有良好的单调性,即服务节点的增减不会造成大量哈希的重新定位。首先,一致性哈希算法会将整个哈希值空间理解成一个环,其取值范围是\(0\sim2^......
  • 代码随想录算法训练营第一天|704.二分查找、27.移除元素
    一、参考资料数组理论基础文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html二分查找题目链接:https://leetcode.c......
  • 代码随想录算法训练营day01| 704. 二分查找、27. 移除元素
    数组基础知识数组是存放在连续内存空间上的相同类型数据的集合。数组下标都是从0开始的。数组内存空间的地址是连续的数组的元素是不能删的,只能覆盖。704二分查找......
  • 【java】冒泡Bubble算法
    冒泡Bubble算法 微信公众号:​​程序yuan​​关注可获得更多干货和视频教程哦。问题或建议,请公众号留言;面试中很常被考到的一道题,就是冒泡排序,可以说是非常经典了参考网上......