KMP


例一:
假如我们要在ABCAABCAB中搜索ABCAB字符串
 
1次比较,我们从第一个字母开始比较,直到比较到红色标记的地方才不相等。
A B C A A B C A B
A B C A B
按我们正常思维,我们会把字符串ABCAB后移一位,从头继续和ABCAABCAB进行比较,如下所示
 
2次比较
A B C A A B C A B
    A B C A B
 
3次比较
A B C A A B C A B
       A B C A B
 
4次比较
A B C A A B C A B
           A B C A B
 
5次比较
A B C A A B C A B
              A B C A B
在第5次比较时,我们在源字符串中,找到了我们需要查找的字符串。
 
总结:
在第2次和第3次的比较中,我们发现这2次比较是无意义的,因为我们知道在我们不匹配的位置前一个字符是A,移动第一次时,是拿CA(不匹配的位置)比较,第二次移动时,是拿B和它比较,直到第3次移动时,才是AA比较。所以理想情况应该是,在第一次比较不满足时,我们就直接后移动3位,进行第4次的比较。
在第一次比较到不匹配的位置时,我们希望把第1A直接移动到第4A的位置(移动3);继续观察ABCA字符串(因为最后一个B已经不匹配了),我们发现AA之间间距3,刚好是已匹配字符串长度4减去A占的位数1。
 
 
 
 
例二:
我们在换一种情况,假如我们要在ABBABABCABC中搜索字符串ABBABC
ABBABABCABC
ABBABC
我们发现最终比较到C时,和源字符串不相等。根据情况一的经验,我们观察前一位字符是B,但是在ABBAB中,前面还有2B,此时我们应该把第1B移动到位置5,还是把第2B移动到位置5呢?还是要做2次移动,比较2次呢?我们在次仔细观察字符串ABBAB,我们发现在ABBAB中,最后2个字符是AB,前面2个也是AB,只有中间一个B,所以理想情况是,我们直接把开头的AB,移动到最后AB所在位置:
ABBABABCABC
ABBABC
如上所示,也就是后移3位。移动位数刚好也等于已匹配字符串长度5减去AB字符串长度2
 
 
 
 
观察情况一和情况二后总结
每次移动,都是在出现不匹配字符时;而每次确定需要移动多少位时,都是根据不匹配字符前面的子串来决定的。我们以例二中的ABBABC为例,假如不匹配的位置出现在ABBABC红色的B时,我们观察ABBA前后共有长度是1(只有A),所以需要后移3位(4减去1)。所以我们依次计算出子串共有长度如下:
A   0
AB   0
ABB   0
ABBA   1
ABBAB   2
ABBABC   0
其实第1个和最后一个共有长度,我们用不到。当比较第1个字符就不匹配时,根本无需计算共有长度,我们自然后移一位。当最后一个字符不匹配时,我们计算出ABBAB的共有长度为2,需要后移5-2位,即3位。

所以在不匹配时,后移位数公式如下:
已匹配子串长度 - 已匹配子串共有长度


既然知道了公式需要用到共有长度,下面我们就说下共有长度如何计算。
A    前缀后缀都为空,共有长度0
AB  前缀[A]后缀[B],共有长度0
ABB  前缀[A,AB]后缀[BB,B],共有长度0
ABBA  前缀[A,AB,ABB]后缀[BBA,BA,A]共有长度(A)1
ABBAB  前缀[A,AB,ABB,ABBA]后缀[BBAB,BAB,AB,B]共有长度(AB)2
ABBABC  前缀[A,AB,ABB,ABBA,ABBAB]后缀[BBABC,BABC,ABC,BC,C]共有长度0

所以 ABBABC字符串 每一位的共有长度为如下
A  B  B  A  B  C
0   0  0   1  2   0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值