主串:"s1...sn"
子串:"p1...pm"
"p1p2...p(k-1)" = "s(i-k+1)s(i-k+2)...s(i-1)" //上次比较了K个相同的字符
"p(j-k+1)p(j-k+2)...p(j-1)" = "s(i-k+1)s(i-k+2)...s(i-1)" //这次比较了K个相同的字符
"p1p2...p(k-1)" = "p(j-k+1)p(j-k+2)...p(j-1)" //这次和上次的前K个字符相同
一般地,使用next[j]表示当模式中第j个字符与主串中相应字符失配时,在模式中需重新和主串中该字符进行比较的字符的位置,即"p1p2...p(k-1)" = "p(j-k+1)p(j-k+2)...p(j-1)"
next[j] 的取值如下:
1. 当j=1时,0
2. 当此集合不空时,Max{k| 1<k<j 且 "p1p2...p(k-1)" = "p(j-k+1)p(j-k+2)...p(j-1)"}
3. 其他情况,1
next[j+1]的求解过程:
模式串自身进行匹配,这里pj作为主串元素看待,pk作为子串元素看待。
1. pk = pj,即 "p1...pk" = "p(j-k+1)...pj",则next[j+1] = next[j]+1 = k+1(自身匹配,后部等于前部)
2. pk != pj,令pj与pk'比较,k'=next[k](即模式未匹配时,next的用法),再比较pk'与pj。若相等则next[j+1] = next[k] +1 = k'+1;否则,继续按模式未匹配处理。
void get_next(SString P, int next[]){
next[1] = 0; next[2] = 1;
k = 0; j = 2;
while(j < P.length){
k = next[j];
if(P[j] == P[k]){
next[j+1] = k+1; j++;
}else{
while(k!=0){
if(P[j] != P[k]) k = next[k];
else break;
}
next[j+1] = k+1; j++;
}
}
}
}
化简后得
void get_next(SString P, int next[]){
j = 1; next[1] = 0; k = 0;
while(j < P.length){
if(k==0 || P[j] == P[k]){
++j; ++k; next[j] = k;
}else{
k = next[k];
}
}
}
后通过next进行匹配即可。