大部分知识体系参考https://blog.csdn.net/x__1998/article/details/79951598


问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢?
目的:主串和子串快速匹配

字符串的前缀和后缀

如果字符串A和B,存在A=BS,其中S是任意的非空字符串,那就称B为A的前缀
例如,”Harry”的前缀包括{”H”, ”Ha”, ”Har”, ”Harr”}
我们把所有前缀组成的集合,称为字符串的前缀集合

同理 后缀和后缀集合也是如此。

PMT(部分匹配值)中的值是字符串的前缀集合与后缀集合的交集中最长元素的长度。

例如,对于”aba”,它的前缀集合为{”a”, ”ab”},后缀 集合为{”ba”, ”a”}。两个集合的交集为{”a”},那么长度最长的元素就是字符串”a”了,长 度为1,所以对于”aba”而言,它在PMT表中对应的值就是1。

对于字符串”ababa”,它的前缀集合为{”a”, ”ab”, ”aba”, ”abab”},它的后缀集合为{”baba”, ”aba”, ”ba”, ”a”}, 两个集合的交集为{”a”, ”aba”},其中最长的元素为”aba”,长度为3。

next数组是为了编程方便不直接使用pmt
它的值就是将PMT数组向后偏移一位得到的
next第0位的值,我们将其设成了-1,这只是为了编程的方便,并没有其他的意义。
求next数组的过程完全可以看成字符串匹配的过程,即以模式字符串为主字符串,以模式字符串的前缀为目标字符串,一旦字符串匹配成功,那么当前的next值就是匹配成功的字符串的长度

也就是说:
从模式字符串的第一位(注意,不包括第0位)开始对自身进行匹配运算
在任一位置,能匹配的最长长度就是当前位置的next值

如果在 j 处字符不匹配,那么由于前边所说的模式字符串 PMT 的性质,主字符串中 i 指针之前的 PMT[j −1] 位就一定与模式字符串的第 0 位至第 PMT[j−1] 位是相同的。因为主字符串在 i 位失配,也就意味着主字符串从 i−j 到 i 这一段是与模式字符串的 0 到 j 这一段是完全相同。
KMP算法学习笔记
模式字符串从 0 到 j−1 ,在这个例子中就是”ababab”,其前缀集合与后缀集合的交集的最长元素为”abab”, 长度为4。主字符串中i指针之前的 4 位一定与模式字符串的第0位至第 4 位是相同的,即长度为 4 的后缀与前缀相同。
我们就可以将这些已经匹配好的字符段的比较省略掉。做法是,保持i指针不动,然后将j指针指向模式字符串的PMT[j −1]位即可。
所以为了编程的方便, 我们不直接使用PMT数组,(因为要j-1),而是将PMT数组向后偏移一位。我们把新得到的这个数组称为next数组。

默认两个指针都从头开始匹配
两个指针指的值一样时都向后匹配下一个字符
如果刚开始就都不相同将整个子串向后挪一位
发现不匹配时将j指针挪动到新的位置(往后挪几位取决于next值是几
移动的位数=已匹配数-next[]

实例:要在主字符串"ababababca"中查找模式字符串"abababca"
KMP算法学习笔记
实例视频:https://v.youku.com/v_show/id_XMzUyMjQyMTE3Mg==.html
(2:15)

相关文章: