KMP算法(中)next数组求法详解

next函数值取决于模式串T本身和相匹配的 主串S无关

设next[j]=k,则p[0]p[1]----p[k-1]=p[j-k]-----p[j-1],那么next[j+1]=?

(2)设next[j]=k,p[k]!=p[j]

p[0]...p[k-1]==p[j-k]-----p[j-1]

求next函数值问题看成一个模式匹配问题,模式串既是主串又是模式串

在当前匹配的过程中,已有p[j-k]=p[0]......p[j-1]=p[k-1],但是p[j]!=p[k],(执行get_next函数中的else k=next[k]),于是模式串向右滑动第next[k]个字符和主串中第j个字符比较。若next[k]=k',若p[j]=p[k'],说明主串中第j+1个字符之前存在一个长度k'(即next[k]=k')的最长子串,和模式串中从首字符起长度为k'的子串相等:p[0]----p[k']=p[j-k']---p[j]

也就是:next[j+1]=k'+1(但是next[k]==k')next[j+1]=next[k]+1

同理,p[j]!=p[k'],模式继续向右滑动直至将模式中第next[k']个字符和p[j]对齐------------------依次类推

 1 public static int[] getNext(String ps) {
 2 
 3     char[] p = ps.toCharArray();
 4 
 5     int[] next = new int[p.length];
 6 
 7     next[0] = -1;
 8 
 9     int j = 0;
10 
11     int k = -1;
12 
13     while (j < p.length - 1) {
14 
15        if (k == -1 || p[j] == p[k]) {
16 
17            next[++j] = ++k;//等价于++j,++k;next[j]=k;
18 
19        } else {
20 
21            k = next[k];//不相等模式串前移,如果一直不等,则一直前移
22 
23        }
24 
25     }
26 
27     return next;
28 
29 }

 

 tips:关于循环一定注意边界条件

其实,主串和模式串都是p,它的匹配过程和kmp算法类似(只是主串和模式串一样)

辅助理解:严蔚敏《数据结构》81页,关于kmp的两种情况

 在求得模式的next函数之后,匹配可如下进行:假设以指针i和j 分别指示主串s和模式t中正待比较的字符,令i的初值为0j的初值为0。若在匹配过程中 ,s[i]==t [j]   ,则 i 和j 分别增1,否则,i不变,而j退到next[j]的位置再比较,若相等,则指针各自增1,否则j再退到下一个next 值的位置,依次类推,直至下列两种可能:

一种是j 退到某个next 值(next [...next[j]...]])时字符比较相等,则指针各自增1,继续进行匹配;

另一种是j 退到值为-1(即模式的第一个字符“失配”,第一个字符对应数组的0号单元,所以数组0号单元失配则则退到0号单元的左边),则此时需将模式继续向右滑动一个位置,即从主串的下一个字符  s[i+1]   起和模式重新开始匹配。

next函数:时间复杂度O(m)

KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。其KMP算法的关键在于求解模式串P的next数组。下面详细介绍next数组的含义、求解方法以及应用。 1. 含义 next数组是一个长度为m(m为模式串P的长度)的数组,其next[i]表示P[0:i]这个子串,最长的既是其前缀又是其后缀的字符串的长度。特别地,next[0]=-1,next[1]=0。例如,当P="abab"时,其next数组为[-1,0,0,1]。 2. 求解 next数组的求解可以通过动态规划的方式实现。具体来说,在求解next[i]时,假设已知next[0:i-1]的,我们需要找到一个最长的既是P[0:i-1]的前缀,也是P[1:i]的后缀的字符串。这个字符串可以通过比较P[0:j-1]和P[i-j:i-1]来得到,其j=next[i-1]+1。 如果P[j]==P[i],那么next[i]=j;否则,我们需要找到一个更短的字符串。此时,我们可以利用next数组的性质,从next[j]开始向前查找,直到找到一个P[k]等于P[i]为止,然后令next[i]=k。如果一直找到k=-1还没有找到,那么next[i]=0。 3. 应用 有了next数组之后,我们就可以利用KMP算法在文本串S查找模式串P的出现位置。具体来说,我们维护两个指针i和j,分别指向S和P的当前位置。如果P[j]==S[i],那么i和j都向后移动一位;否则,我们利用next数组来决定j的下一步移动位置。具体来说,如果next[j]=-1,或者next[j]<i,则令j=0,i不变;否则,令j=next[j]。这样,我们可以在O(n+m)的时间复杂度内完成匹配。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值