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的初值为0,j的初值为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)