如何向小学生解释KMP算法的原理?

小学生擅长形象思维,用图画方式给他们解说比较好。另一个方面来讲,形象思维不就是二维语言么,比一维的文字语言概括性高点,精确性低点。
先给个具体场景:有个字符串“你大爷还是你大爷
现在要在一个文本中精确查找是否有这个字符串。假设文本很长很长,长得小学生懒得看(老师问:为什么不写作业?学生答:懒——得写。老师:啊?!)
该文本部分内容如下:

天苍野茫风吹现牛羊你大爷我在尚书房你大爷还是你大爷邻家小妹在远方。。。。。。
你大爷还是你大爷

所谓查找,实际上就是比较。现在要将“你大爷还是你大爷”这作为一个整体数据在文本中进行查找。还记得在数组中查找指定的某个值查找方式么?就是遍历数组,依次拿出数组中的乜咯元素和指定元素进行对比:相等,查找成功;不等继续拿出元素对比。
能否将这种思路也迁移到这种字符串匹配呢??
当然可以,咱试试。
首先考略下两者场景的不同点。数组中找指定元素,指定元素和数组中单个元素的长度是一致的,都是1,所以每次将比较的游标从数组当前位置往后挪一位,就可以找到待比较的数组元素。但是字符串匹配中,文本中的元素长度单位还是1,但是指定的字符串长度超过了1,在本文中是8.那么每次比较的时候,游标是否还是向后移动一位呢?
当然是的!因为每移动1位,然后向后扩展到长度为8的单元,就可以和指定长度为8的字符串进行比较了。所以会发现,在这种字符串的匹配中,还是可以类似遍历的方式来查找。那么要查找多少次呢?
最坏情况就是该字符串在文本的末尾,大概就是文本长度的次数了(O(n))
如下图:指定字符串“你大爷还是你大爷”每次移动1个汉字长度,然后和文本内容进行比较。

天苍野茫风吹现牛羊你大爷我在尚书房你大爷还是你大爷邻家小妹在远方。。。。。。
你大爷还是你大爷

天苍野茫风吹现牛羊你大爷我在尚书房你大爷还是你大爷邻家小妹在远方。。。。。。
  你大爷还是你大爷

天苍野茫风吹现牛羊你大爷我在尚书房你大爷还是你大爷邻家小妹在远方。。。。。。
    你大爷还是你大爷

这样查找可以查找出来,但是有些人觉得这样遍历整个文本,这浪费计算资源啊,LowB!

于是乎在减少遍历次数上做文章。

减少遍历次数的方式很多,其中kmp(看k毛m片p)算法给的是其中一种方式,可以减少遍历次数。
那么这种算法具体实现其实是基于被指定对象“你大爷还是你大爷”本身特点来执行的。
第一步,我们用一个新的视角来观察这个字符串的特点:
在这里插入图片描述
看看我们是怎样来分析这个字符串的:
首先将该字符串第一个字符串取出来“你”,以该字符串中间中间位置为对称轴,找左右两边对称的字符串,然后在这些字符串中找到长度最大的一组,并记录长度。
如上图所示,一直到当字符串增长到完整字符串时候“你大爷还是你大爷”,可以发现该字符串中间位置在“还”“是”之间的间隔。(1.找对称位置)
以此为对称轴找对称的字符串,‘“你大爷”和“你大爷”(2.找对称字符串)
数出该字符串的长度。“你大爷”.length = 3 ;
将3作为一个元素存入与“你大爷还是你大爷”等长的数组中,存放位置就是对应该字符串的长度。(3.确定指定字符串每一位上对应的对称最大值)

这样一来“你大爷还是你大爷”观察出来了一个数组[0,0,0,0,0,0,0,3]

费尽周折观察这个字符串可不是白弄得,这个就是被指定字符串移动多少位的依据。

 天苍野茫风吹现牛羊你大爷我在尚书房你大爷还是你大爷邻家小妹在远方。。。。。。
        你大爷还是你大爷

情观察上面,野茫茫的“野”与“你”做对比,发现不匹配,那么要将“你大爷还是你大爷”向后移动,移动多少位呢?这个有个依据,不是最普通每次都定死的移动1位,这个依据就是数组[0,0,0,0,0,0,0,3]。
怎么使用这个数组中数字呢?
很简单,就是当不匹配这种事情发生在指定字符串哪个字符时候,就使用这个字符对应的那个数字。
现在看发生不匹配的发生在字符串“你大爷还是你大爷”的第一个“你”,这个“你”对应数字为0,那么这个0就是移动依据。移动后达到什么一个效果?就是在被指定字符串与文本中发生不匹配事件的文本所在位置为标记点,在该点之前所保留的被指定字符串的长度为0.
说了这么多,还是画图最直观:
在这里插入图片描述

接下来就是将从“我”开始与“你大爷还是你大爷”进行对比。重复之前的操作,直到匹配出来。
从中可见,第一次出现“你大爷”三个字向符合的位置处,指定字符串不像往常那样只是向后移动一位继续匹配,而是直接跳了三位来进行匹配。这样就减少了遍历次数。
图示如下:
在这里插入图片描述
这种情况的出现一般指定字符串和文本中有部分内容重叠时候发生。试想想,如果文本除了最后收尾的字符串和指定字符串相匹配,前面所有的都不与之有交集,那么前面的匹配方式依然是每次只移动一位,并没有减少匹配次数。
指定字符串中出现了对称的文字,是kmp算法能够减少遍历次数的关键。所以,指定字符串中如果没有出现对称元素现象,根本没必要使用,那么效果和朴素算法一样,也是遍历。

猜你喜欢

转载自blog.csdn.net/qq_24699905/article/details/86187619