28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
看题解前:只会暴力求解,一个一个匹配
看题解后:经典KMP问题(没学过,现学),推荐观看
帮你把KMP算法学个通透!(理论篇)_哔哩哔哩_bilibili
帮你把KMP算法学个通透!(求next数组代码篇)_哔哩哔哩_bilibili
非常有用。
学完说说我理解的KMP算法吧,最重要的就是学会什么是前缀表,为什么要使用前缀表(使用前前缀表的好处),怎么创建前缀表(给前缀表填充数据)。
什么是前缀表
我的理解就是保存相同前后缀字符串的个数的表
那什么是前后缀?
例如有个字符串aabaaf
前缀:包含第一个字符不包含最后一个字符的字符串叫前缀,如:a,aa,aab,aaba,aabaa;
后缀:包含最后一个字符不包含第一个字符的字符串叫后缀,如:f,af,aaf,baaf,abaaf;
相同前后缀又怎么理解?
aabaaf
字符串a前缀a没有后缀,所以相同前后缀个数为0
字符串aa前缀a,后缀a,相同前后缀个数为1
字符串aab,前缀a,aa;后缀b,ab;相同前后缀个数为0
aaba,前缀a,aa,aab;后缀a,ba,aba;相同前后缀个数为1
以此类推aabaa相同前后缀个数为2
aabaaf为0
此时前缀表即为0 1 0 1 2 0
为什么使用前缀表
首先我们需要知道暴力求解有什么劣势
最大的劣势就在于一旦不匹配我们只能重新全部匹配
前缀表里面的数据能让我们在匹配失败的时候直接跳转到已经匹配过的下一个位置开始匹配从而提高效率
怎么创建前缀表
其实在介绍前缀表的时候就已经讲解了前缀表的数据是怎么填充的了
那个就是前缀表填充数据的原理,那我们怎么用代码来实现填充呢?
这里还是用字符串s=“aabaaf”来举例,定义一个j=0;next[0]=0(因为第一个字符的字串没有后缀,就没有相同前后缀的字符串了所以为0)
定义i=1开始遍历字符串,此时判断s[i]和s[j]是否相等,相等的话j++,第一步相等,此时j++,然后next[i] =j ;i++,这个时候i=2,j=1,前缀表数据为01;s[i] 为b,s[j]为a,不相等,则让j=next[j-1],即j此时为0了,然后next[i]=j,此时前缀表数据为010,以此反复就可以给前缀表填充数据了。可能说的不太通透,建议多看看上述提到的视频讲解理解下。