KMP算法主要是用来字符串的匹配,其作用是可以在线性时间内完成字符串字串的匹配。
其大致原理是这样子的,就是在要匹配的串中,给每一个元素都打上一个标签(next[j]),这个标签可用来后续匹配中,直接就跳过。
假如是这样的,在串S中寻找匹配T的字串
S:ababcababcba
T: ababcb
上面的代码是最简单求next数组的代码
首先给T每个元素打标签
next[1]=0
next[2]=1
next[3]=1
next[4]=2
next[5]=3
next[6]=1
这段代码可以这么理解,比如比较到了第k个元素才发觉有不同,这时候j要回退,回退到哪合适呢?next[j],也就是S[k]与T[next[j]]比较即可。
打个比方,比如上面那个代码中,第4个元素产生了差异,那么next[4] = 2,也就是直接拉第2个元素过来比就行,因为第3个元素跟第1个元素是相同的,这样是不是节约了很多时间。
同理第5个可以这么理解因为第五个前面两个元素‘ab’ == 第一二两个元素,所以直接拿第三个过来就行。
第6个就更明显了,直接就可以过来拿第1个比,因为前5个元素找不到任意组合来匹配倒序
所以求这个next[]的目的是匹配的字串,先自我做一个简单匹配,回掉j的时候会很方便
这部分代码还有改进部分,i++,j++后比如T[i] == T[j],那么next[i] = next[i-1];else next[i] = next[j];前提当然是先按照上面的代码算出next[i],其实只要做如下修改
算完next[]之后,就可以开始比较了。当比较遇到不同的字符元素的时候,不用跳转i,直接跳转j。j=next[j]
以上面的例子为例,第六个元素,两个字符元素不同。next[6] = 1。也就是第一个元素直接就拉倒第六个元素这边来了。
其大致原理是这样子的,就是在要匹配的串中,给每一个元素都打上一个标签(next[j]),这个标签可用来后续匹配中,直接就跳过。
假如是这样的,在串S中寻找匹配T的字串
S:ababcababcba
T: ababcb
next[1]=0;i=1;j=0;
while(i<=T[0]){
if(j == 0 || T[i] == T[j]){
++i;++j;next[i] = j;
}else{
j = next[j];
}
}
上面的代码是最简单求next数组的代码
首先给T每个元素打标签
next[1]=0
next[2]=1
next[3]=1
next[4]=2
next[5]=3
next[6]=1
这段代码可以这么理解,比如比较到了第k个元素才发觉有不同,这时候j要回退,回退到哪合适呢?next[j],也就是S[k]与T[next[j]]比较即可。
打个比方,比如上面那个代码中,第4个元素产生了差异,那么next[4] = 2,也就是直接拉第2个元素过来比就行,因为第3个元素跟第1个元素是相同的,这样是不是节约了很多时间。
同理第5个可以这么理解因为第五个前面两个元素‘ab’ == 第一二两个元素,所以直接拿第三个过来就行。
第6个就更明显了,直接就可以过来拿第1个比,因为前5个元素找不到任意组合来匹配倒序
所以求这个next[]的目的是匹配的字串,先自我做一个简单匹配,回掉j的时候会很方便
这部分代码还有改进部分,i++,j++后比如T[i] == T[j],那么next[i] = next[i-1];else next[i] = next[j];前提当然是先按照上面的代码算出next[i],其实只要做如下修改
next[1]=0;i=1;j=0;
while(i<T[0]){
if(j == 0 || T[i] == T[j]){
++i;++j;
if(T[i] != T[j]) next[i] = j;
else next[i] = next[j];
}else{
j = next[j];
}
}
算完next[]之后,就可以开始比较了。当比较遇到不同的字符元素的时候,不用跳转i,直接跳转j。j=next[j]
以上面的例子为例,第六个元素,两个字符元素不同。next[6] = 1。也就是第一个元素直接就拉倒第六个元素这边来了。
while(i <= S[0] || j <= T[0]){
if(S[i] == T[j]){
i++;j++;
}else{
j = next[j];
}
}