leetcode 3.无重复字符的最长子串

关键就是这个无重复,KMP算法算的是最长子串,本身就不怎么会KMP,然后它还要不重复的,一般寻找子串程序会给你两个结果,一个是子串起始位置,第二个是字串长度,其实还应该有第三个结果,即子串数量,这个看网上题解会更快一些。

关于KMP算法,它本来是在一个字符串里寻找另一个字符串的程序,再复杂一点才是在字符串里面寻找最大子串,因此kmp算法挺适合找子串位置的。

next数组的特点是从1开始,为什么从1开始呢?那要看next数组是什么,它代表的是字符串每一个位置的最大公共长度,什么意思呢?就是next数组表示的是长度,举个例子吧:

这里有字符串A,和字符串B,字符串B有next数组,然后从字符串A里面找字符串B,最开始自然是从头开始比较,假设一开始都是一样的,例如字符串A是QWER*******,字符串B也是QWER$$$$$$,它们前面是一样的,因此可以接着比对下去,等到突然有一个地方,二者不同了,那么说明这一段与B不像,自然不算数,那么接下来怎么办呢?按照常规方法,就是字符串A从W开始,也就是从第二位开始,B字符串从Q开始,还是从第一位开始,比对,然后不同的话字符串A紧接着移动到下一位,就这样,这是普通做法。

KMP呢,它采用的不是字符串A后退法,它采用的是字符串B前进法,一旦不同了,它不是还有一个next数组么,它指定的是最近一个相同的字符位置,我这么说肯定不清楚,因为我自己都说不清楚,举个例子:

字符串A:QWEQWEQ*******
字符串B:QWEQWET*******

假设它们从头开始比较,比较到这一位,不一样了,这时候字符串B开始前进

QWEQWEQ******                                    QWEQWEQ********
   QWEQWET******                                          QWEQWET*******

这两种方法哪一种更快呢?自然是B方法更快,这就是next数组的功劳,next数组之所以能用得上,是因为之前的字符有重复的,如果前面没有重复的,那么自然也用不上,它的实质是一个字符的前几位会与更远的几位有重合,一旦对比不同,就直接跳到那几位而不是从头开始。

因此,怎么生成这个next数组呢?首先它是从下标1开始,也就是第二位,因为第一位之前就没有字符了,更重要的是,我们需要把第一位设置成一个标志位,标志结束,不用再往前移动了,设为-1,第一位肯定设为0,因为一旦不对,它只能从头开始了,然后从第二位开始,它是一个自己比对自己的过程,第一步,设[0]=-1,第二步,将B2[0]移动到B1[1]的位置开始比对,如果相同,即B[0]==B[1]的时候,将next[1]设为0,然后比对B2[1]和B1[2],如果开始相同,设next[2]=1,也就是说,如果比对相同的时候,设此时的next为上一位字符的索引。

如果不同呢?那么就是移动B2了,因为B2始终滞后于B1,因此用next绝对没问题,然后切换到next的那一个位置(前提是有啊),此时便能够保证之前的字符是一样的,但不能保证这个字符是一样的。

从开始第三位与第二位进行比对,相同,设为上一位,不相同,切换next,相同,设为上一位,不相同,切换next,,,,直到0,到位置0后,如果相同,继续比对下去,如果不同,就都向下移动一位,就这样。

既然能比对下去,说明之前的的确是对的上的,那么取更短的一点,自然也能对的上,也就是说,本身比对的那个并不是相等的,才会有next的跳跃。也就是说,在创造next数组的时候,如果二者相等,那么B1[i+1]要设定B2[j+1]的那个索引,这是非常巧妙的办法。











 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值