分享一下自己关于KMP模式匹配算法的理解

朴素的匹配算法

主字符串:abababc
副字符串:ababc

前四个字符相等,匹配到第五个字符时发现不等,朴素算法会从主串的第二个(主串指针从第五个减到第二个)开始重新匹配副串的第一个(副串指针从第五个减到第一个),重复这个过程,相当于把主串中所有与副串等长的连续子串拿出来验证,验证它是否等于副串。最坏情况下的时间复杂度是O(n*m)。

朴素算法待改进之处

如果存在与副串相匹配的子串,假设这个字串和我们已经匹配过的主串的前4个元素根本没有交集,那把主串的指针向后调整只会浪费时间,我们应该从失败的地方直接重新匹配;
而如果这个字串和前面4个元素有交集,我们并不知道哪一个是,所以我们因该把主串的指针尽量多的向后调整,以免错过了最终答案。比如,我们这个例子中如果最终的字串和前四个元素有交集,显而易见,交集只可能是第3个a和第4个元素b。

上面说的向后调整指针,并不需要调整主串的,因为既然有交集,那主串指针原地不动,
向后调整副串指针,让副串和交集左对齐。比如,我们这个例子中让副串的第一个元素a和主串第三个元素a对齐。这时主串指针为5,与主串相对应位置的副串指针为3。这用作在算法的正确性上和后调主串指针到位置3,副串指针到位置1,是完全相同的,但是前者更加高效。

继续运行我们的算法,后面的bc两个元素也都相等,所以匹配成功。

KMP的基本原理

继续上面话题,既然是交集,那主串34位置ab必然也出现在副串的最前面12位置,而前面1234位置的主串副串相等,主串34位置也就是副串的34位置,所以副串的12位置和34位置相等。这说明了交集的一个性质:假设j为副串中匹配失败的地方,副串表示为S(1)…S(m),那么长度为l的交集为S(j-l)…S(j-1),并且和S(1)…S(l)相等。我们正是要找每次匹配失败时这样的最长交集,因为这等价于把主串指针后调了尽可能多的距离。

提前准备——next[]

从上面的交集性质可以看出,这个交集和主串没有关系,只要指定副串和j(匹配失败的地方),我们就可以找到这个最长交集,所以在运行匹配算法前,我们的任务是先找出每一个j所对应的交集长度,可以用数组记录,但是我们没有直接记录它,为了编程方便,我们用数组next[j]来表示:如果位置j上发生匹配失败,那下一个参与匹配的副串位置为next[j]。

next的构建——动态规划

我们初始化next[1]=0(哨兵),next[2]=1(显而易见),这里next的构造思想很像动态规划,都是根据前面的next推后面的。比如,副串ababababcd在最后面d这个位置上匹配失败,要是存在非空交集,那么d前面的c需要加入到交集的序列最后,我们已知了c前面b为结尾的交集的最长长度,如果c可以加入到那个交集结尾,得到的新交集必然是最长的,也就是next[10]=next[9]+1。判断可不可以加入进去也很简单,只需要看一下S(j-1)和S(next[j-1])是不是相等就可以了,这里体现了next数组存储下一个比较位置的好处,如果存长度,需要比较S(j-1)和S(next[j-1]+1),这个例子中比较的是位置3的a和位置5的c,比较结果不相等。

上面的比较中隐藏了两个字符串:
位置56789:ababc
位置12345:ababa
这里采用之前关于kmp基本原理的分析方法,可以看出这又是一个主串和副串匹配的问题,显然匹配在最后一个失败了,但是我们不用从头开始匹配,调用next[5]就可以知道下一次匹配是在位置3,我们把位置3和位置9的字符比较,也就是:
位置789:abc
位置123:aba
假设成功,那么next[10]=next[5]+1=4。这里当然没有成功,j=3,下一个比较的地方是next[3],显然需要从头开始比较,无论下次比较成功与否,next[10]=1,而不是2或者0。

应用于实际问题时应该注意的地方

具体的算法实现网上有很多模板,这里没有介绍,大家也可以在杭电oj上问题的评论里找。
http://acm.hdu.edu.cn/showproblem.php?pid=1686
这道题中需要另外注意的一点,next数组一直算到了匹配字符串最后一个空字符,因为第j项代表第j项匹配失败时,前面0~j-1的最长的交集,如果没有这最后一个空格字符的next值,我们需要在这时i–,并j–,再j=next[j],一定注意i和j的对应。
杭电oj上还有很多关于模式匹配的题,可以在相似问题中找到,下面列出几个供大家参考:
http://acm.hdu.edu.cn/showproblem.php?pid=1686
http://acm.hdu.edu.cn/showproblem.php?pid=2087
http://acm.hdu.edu.cn/showproblem.php?pid=1711
另外,其他常用的模式匹配方法还有AC自动机,字典树等。

猜你喜欢

转载自blog.csdn.net/weixin_40770091/article/details/87913239
今日推荐