注:该篇为简洁推理笔记,需预先理解KMP原理,改篇只为备忘查询使用。其中推理和表述非常不严谨,但作为备忘非常好用
主串:一般是长的那个
模式串:一般是短的那个
问题:在主串中找模式串
概要步骤(含推理)(懒得用flowchart了)
1. 从模式串第一个字母开始挨个和主串第一个字母开始挨个对比
2. 这个字母匹配上了,j++,i++,j>模式串.len() break or return true(匹配上了)
3. 但凡中间有一个匹配不上就在主串中往前挪n个字母i-n,模式串中往前挪x个字母j-x后开重新比对
4. 以主串[i],模式串[j]为起点重复1-3 直至到主串末尾后return false
问题:
步骤3中往主串前挪多少,模式串后挪多少。x,n各是多少比较合适
解决:
n = 0, i永远向前进
x = 和当前j有关,j往前挪多少取决于当前的j是多少,(神奇!就是这么的神奇!)
甚至有一个数组专门记录j往前挪多少next[模式串.len()]
与其记录往前挪多少x不如更方便的记录应该挪到模式串的哪个位置那么next就记录下次移动的位置
概要步骤改进
1. 从模式串第一个字母开始挨个和主串第一个字母开始挨个对比
2. 这个字母匹配上了,j++,i++,if j>模式串.len() return true(全部匹配上了)
3. 但凡中间有一个匹配不上,i不动,模式串中j = next[j]
4. 以主串[i],模式串[j]为起点重复1-3 直至到主串末尾后return false
神奇!就是这么的简洁!
问题:
如何构造next[模式串.len()]
next[j]取决于模式串当前j前面多长的一块堆儿(和数据结构那个堆没关系,只是口语)和模式串开始前面的多长一块堆儿长度相同。
构造next
next[0] = 0; 第一个就没匹配上,那j还是第一个,到时候得特意弄个i++
next[1] = 0; 第二个只要没匹配上还是要回去的
准备两个mover
header和tail
初始header置0(指到next第一位的前面)
tail置2(指向第3位)
如果 模式串[tail - 1]== 模式串[header]
next[tail] = header+1
// 直接预先检查一下,如果上一个header+1对应的值和这次一样,那也别比了,直接再往回找补吧
if(模式串[tail] == 模式串[header+1])
next[tail] = next[header+1]
header++
tail++
否则
// 将header回退, 但是不直接退到0退到上一个匹配点再试试看能不能匹配上,不行的话继续退
header = next[header]
重复直至 tail == 模式串.len()-1
本文提供了一种简洁明了的KMP算法推理方法,帮助读者快速掌握模式串匹配过程及next数组构建技巧。

1万+

被折叠的 条评论
为什么被折叠?



