对力扣:28. 找出字符串中第一个匹配项的下标,其中kmp算法求next数组循环回溯的理解

题目链接

题目答案求next数组部分代码如下

void getNext(int* next, const string& s){
    int j = -1;
    next[0] = j;
    for(int i = 1; i < s.size(); i++) { // 注意i从1开始
        while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了
            j = next[j]; // 向前回退
        }
        if (s[i] == s[j + 1]) { // 找到相同的前后缀
            j++;
        }
        next[i] = j; //j正好是子串长度
    }
}

之前对于求next数组中的while回溯逻辑一直不是很理解,所以此文章主要解释while循环中的逻辑,所以对于kmp算法完整教程请见其他文章。

其实在求next数组过程中,要记住两点,首先求next这个过程其实也是在进行子串和主串在进行匹配的过程,第二点是,如果子串和主串不匹配的时候,子串回溯到哪里,是和主串没有关系的,只和子串长什么样有关。
在求next数组过程中,因为前缀部分的起点是固定的,后缀部分是变化的,所以其中j指针控制的部分为前缀部分,我们把它看成子串,i指针控制的部分为后缀部分,我们把它看成主串,求next数组即在求最大前后缀公共长度无非是不断地加大它们之间的长度看他们匹不匹配,这也是在进行字符串匹配的过程,知道了这件事情之后,整件事情就好理解了。
再来看求next数组过程中可能出现的两种情况,无非是匹配失败和匹配成功两种结果,而在匹配失败的时候,我们就需要缩短比较长度了,要缩短刚才对比的子串的前几个,但是根据kmp的思想,我们不能直接让主串回溯从新开始比较,只要让模式串回溯到合适位置即可,因为刚才的next数组已经保留了前面可能已经匹配上的字符,而且回溯到哪里,是和主串没有关系的,所以我每轮不管i控制的后缀部分是什么样,我都可以遵循这个逻辑进行回溯再次进行匹配,如果j没有回溯到最开始说明前后缀有一些公共的部分,下次可以接着使用,此时j正好又是字串长度,所以在求next数组过程中不必太关心后缀,因为它就相当于匹配过程中的主串,而且返回的长度也是j控制的前缀部分的,也就是相当于匹配中的从串。直到我匹配成功位置,就可以接着往下匹配尝试加大前后缀长度看是否仍然匹配。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值