1.假设模式串(子串)p: 为 "bbabba" ,扫描模式串的指针为j, 当扫描到模式串不匹配的时候模式串回退的位置为k
需要弄清楚的是next数组的含义,比如next[j] = k表示的是当p[j] == p[k]的判断不成立的时候(失配)k应该回退到模式串的下标为k的next[k]位置上
比如模式串为bbabba,下面是求解过程
b b a b b a
(p[k]为该行中字后一个字符,写成下面的形式是为了更好的观察,其实还是同一个字符串)
p[0] = b b netx[0] = -1 j = 0 k = -1
p[1] = b b b next[1] = 0 j = 1 k = 0
p[2] = a b b a next[2] = 1 j = 2 k = 1
p[3] = b b b a b next[3] = 0 j = 3 k = 0
p[4] = a b b a b a next[4] = 2 j = 4 k = 1
p[5] = a b b a b b a next[1] = 2 j = 5 k = 2
要求解next[2],首先要看上一次的p[j]和p[k] 其中上一次的j和k为:j = 1 k = 0
判断p[1]是否等于p[0] 假如相等则next[2] = ++k = 1, 假如不相等k = next[k],在这里例子中p[1] = p[0] ,所以next[2] = ++k = 1
求解next[3] , 其中next[2] = 1 : j = 2 k = 1 那么判断p[2]是否等于p[1] ,这里p[2]!=p[1]所以 j = 2 k = next[1] = 0 判断p[2] 是否等于p[0] 发现不等那么j = 2 k = next[0] = -1,此时 k = -1,当k = -1 的时候next[3] = ++k = 0
求解next[4], 其中next[3] = 0 : j = 3 k = 0 那么判断p[3]是否等于p[0] 发现相等那么next[4] = ++k = 1
求解next[5], 其中next[4] = 1 : j = 4 k = 1 那么判断p[4]是否等于p[1] 发现相等那么next[5] = ++k = 2
那么模式串 "bbabba"的next数组为 : -1 0 1 0 1 2
上面的模式是基于代码的思路来的
求解next数组实际上也是求解最长前缀与最长后缀的最长匹配,比如像上面的模式串 "bbabba"(求解next[k]不包含模式串下标为k这个位置的字符所求解的前缀和后缀)
第一次next[0]]: b next[0] = -1
第二次next[1]: bb next[1] = 0
第三次next[2]: bba 求解next[2]的时候不包括bba的最后一个字符,所以bba的前缀为: b
后缀为b 所以最长前缀与最长后缀的最长匹配为b,有一个所以next[2] = 1
第四次next[3]: bbab bbab的前缀为: b和bb
后缀为a和ba,前缀和后缀都不匹配,所以next[3] = 0
第五次next[4]: bbabb bbabb的前缀为: b, bb,bba
后缀为b,ab,bab,所以最长前缀与最长后缀的最长匹配为b,有一个所以next[4] = 1
第六次next[5]: bbabba bbabba的前缀为: b, bb,bba,bbab
后缀为b,bb,abb,babb,所以最长前缀与最长后缀的最长匹配为bb,所以next[5] = 2
2. 下面是具体的代码实现:
public class Next{
public static void main(String[] args) {
String p = "bababb"; //next:-1 0 0 1 2 3
int next[] = next(p);
for(int i = 0;i<next.length;i++){
System.out.print(next[i]+" ");
}
}
private static int[] next(String ps){
char p[] = ps.toCharArray();
int next[] = new int[ps.length()];
next[0] = -1;
if(p.length==1)return next;
//定义两个指针用来指向扫描到模式串和假如不匹配会回退到的位置k
int j = 1;
int k = 0;
//因为下面++j所以j<next.length-1
while(j<next.length-1){
if(k==-1||(p[j]==p[k])){
next[++j]=++k;
}else{
k = next[k];
}
}
return next;
}
}
其中还有其他例子:
String p = "ababaa"; //next:-1 0 0 1 2 3
String p = "bababb"; //next:-1 0 0 1 2 3
String p = "bbabba"; //next:-1 0 1 0 1 2
String p = "babbab"; //next:-1 0 0 1 1 2
想的时候可以求解next数组的时候是求解最长前缀与最长后缀的重叠部分