假设A=“abababaababacb”
B=“ababacb”
用i指针表示A串:A[i-j+1…i]表示A串从
基本思想:i不断增加,随着i的增加j相应地变化,且j满足以A[i]为结尾地长度为j的字符串正好匹配B串的前j个字符(j当然越大越好)。然后,检验A[i+1]和B[i+1]的关系————
当A[i+1]=B[j+1]时,i和j各加一;什么时候j=m了,我们就说B是A的子串(B串已经整完了),并且可以根据这时的i值算出匹配的位置。
当A[i+1]不等于B[j+1],KMP的策略是调整j的位置(减小j值),使得A[i-j+1…i]与B[1…j]保持匹配且新的B[j+1]恰好与A[i+1]匹配(从而使得i和j能继续增加)。
int ans=0,j=0;
for (int i=0;i<n;i++)
{
while (j>0&&B[j+1]!=A[i+1]) j=P[j];//不能继续匹配且j还没减少到0,减少j的值
if (B[j+1]==A[i+1]) j++; //能继续匹配,j加1
if (j==m){ //找到一处匹配
printf("%d\n",i-m); //输出子串串首在母串中的位置
j=P[j]; //继续寻找匹配(可重叠)
}
}
//一句话理解算法:
扫描字符串A,并更新可以匹配到B的什么位置
void pre(){
P[1]=0;int j=0;
for (int i=1;i<=m;i++){
while (j>0&&B[j+1]!=A[i+1]) j=P[j];
if (B[j+1]==A[i+1]) j++;//能匹配,j加1
P[i+1]=j; //每趟循环要求的是
}
} //要点:1、B串的自我匹配;
// 2、计算匹配的长度