这篇文章主要说明我思考许久的一个问题就是下方图片中的while循环为什么不能直接让k归0,而一定要用while循环一点一点让k跳到0.
下方两张图片第一张是我最开始自己实现时的代码思路,第二张是官方正确答案,主要分析我自己思路出现的问题,以及我对next数组的一些理解
我的写法:(i--和continue可以省略,效果一样,但都是错误的)
正确写法:
先说明:上方两种写法在输入的字符串中没有二次及更多次重复包含时结果相同,如字符串"ABCDABCDABCDABCC";当有二次重复包含时我的结果是错误的如字符串"ABCDABEEEEABCDABCD",所谓二次包含即ABCDAB重复包含了AB
错误分析:我的思想是直接跳过ABCDAB从C开始重新判断,而正确的做法应该是带上重复包含的AB用ABC进行重新判断,这是我所没有注意到的点,也是为什么使用while循环的原因所在,下方是两种运行结果的对比,是否明白了一些什么?
了解到错误原因后我们来说一说正确的代码应该如何理解。先说结论:while循环每一次运行都会使k按照某一规律跳到某处(类似于ctrl+f查找相同元素的效果),有两种结果,一是跳到的位置元素与i处元素相等中途退出循环,即存在子串包含,或是一直不等最终回到起点0,即不存在子串包含。
1.判断C和E不相等进入while循环
2.k由E所在位置开始回溯,k-1=5,5对应next值为2,下标2位置元素为C,C与I所在位置元素作比较很显然(上图中已经标出i所在位置元素为C)两方相等退出循环k的最终值为2
3.为什么最终k的赋值为3呢,答:因为下方还有一个if条件判断,成立后对k值进行了加一,再赋值,所以while和if的位置不可调换,除了k++会影响while的条件判断外,还有这一层原因
4.这种写法是如何想出来的,为什么能达到这种效果?对于这个问题我只能说,算法的设计者很巧妙的利用了,next数组中值与下标的对应关系,没错他们之间存在一种规律,比如k每一次循环的落点都刚好是最近的重复数字的下一位,这也许是根据数学原理推导出的,也许是怎么想到的,其实这些你无需关心,这是一种规律,记住就好,没必要深究。
5.如果while的写法k的最终落点为0,那么你要知道,这个字符串中不存在字串包含,也就是说,我的错误写法将会和正确写法运行结果一至,这也是我最开始百思不得其解的地方,也是我记录这篇文章的原因所在,虽然我的错误写法存在问题,但它也帮助我记住了正确写法,遇到问题要想办法验证正确与否并尽快解决,不要拖到明天,特此记录。