1.KMP匹配
假定有
主串 S = s1s2s3s4s5s6....sn;
模式串 T = t1t2t3t4t5t6...........tm;
很容易想到的模式匹配算法为两重循环暴力求解但是这样在很多情况下时间复杂度不能满足要求,例如主串和模式串都较大的情况
那么我们就需要对这个朴素的算法进行一些优化。
首先考虑一下当我们一遍匹配之后我们能够得到什么信息
主串 S:
s1s2s3 s4 s5 s6........si
模式串T
t1t2t3 t4 t5 t6..........tj
假定我们在si和tj处失配了,那么我们能够得到的比较明显的信息就是“s1s2s3s4s5s6...si-1”="t1t2t3t4t5t6....tj-1"
现在匹配失败了,如果按照朴素的算法我们应该把主串的指针回溯到s2,把模式串的指针回溯到t1,那么问题就来了,要是s2与t1不匹配呢,那么我们就要接着试s3,
要是s4不匹配那就s5。。直到找到匹配的。
这样感觉有点低效的样子,大部分时间都花在了枚举上面,而且有太多重复的无用信息
要是我们能找到一种能够快速找到匹配位置的优化方式这样是不是就能解决问题了呢。
那么要怎样找到这个优化方式呢,核心思想是利用以前匹配时得到的部分匹配信息
我们先倒回去看我们上一次匹配收集到的信息“s1s2s3s4s5s6...si-1”="t1t2t3t4t5t6....tj-1"
我们假定在“s1s2s3s4s5s6...si-1”="t1t2t3t4t5t6....tj-1"中除s1外还有与t1相等的位置为sx,那么我们能推出"sx.....si-1"="ty......tj-1"
要是我们能够在T串中找到一个真子串"t1......tz"="ty.....tj-1"
同理我们就能够得到"t1......tz"="sx.....si-1"
既然这样的话我们就能够使主串指针保持不动为i,让模式串的指针为z+1,这样开始匹配就能节省大量的枚举操作
事实上我们观察之后发现,其实我们实现上面这种优化的时候所用到的信息都是T串中的信息,当tj失配之后我们采取的方式是在T串上回退
我们把这个回退数用next数组保存,当tj失配时回退到next[tj],关于next数组和nextval数组的求法可以查看我以前的一篇博客点这里
自此一种字符串匹配优化算法就介绍完毕,这种优化之后的算法就是传说中的KMP