KMP算法:就是按自左向右的方向进行匹配,在匹配过程中,当模式串P不匹配时,应尽量向右移动最大距离,以避免重复比较。
假设目标串T=t0,t1,t2,,,,,,tn模式串P=p0,p1,......pm,在模式串匹配的过程中出现了不匹配位ti!=pj,如果下一步比较的是ti和pk,需要满足什么条件呢,
一方面有:ti-k,ti-k+1,,,,ti-1=pj-k,pj-k+1,,,,,pj-1;
另一方面:ti-k,ti-k+1,,,,ti-1=p0,p1,,,,,pk-1
因此:pj-k,pj-k+1,,,,,pj-1=p0,p1,,,,,pk-1;
下面就引入部分匹配串的概念:
首先对模式串p进行与预处理,对于p在j位置找出所有的 前缀合后缀,其中最大的一对相等的p[0..........j]的前缀和p[1,,,,,,,j]的后缀为部分匹配串。
怎样求模式串每个位置上的部分匹配串长度呢,下面引入next函数,next'[j]的值表示了模式串p在j位置的部分匹配串长度。
下面给出next函数的算法:
void next(char *p,int next[])
{ int m=strlen(p);//模式串p的长度。
next[0]=0;//位置0处的部分匹配串长度为0
int i=1,j=0;//初始化比较位置
while(i<m)
{ if(p[j]==p[i])//已经匹配了j+1个字符,
{ next[i]=j+1;//部分匹配串长度加1.
i++;j++;//比较的各个位置加1.
}
else{ if(j>0) j=next[j-1];//移动,用部分匹配串对齐。
else next[i++]=0;//j在串头部分匹配长度为0.
}
}
}
匹配算法:
int KMP_match(char *T,char *p)
{ int n=strlen(T);
int m=strlen(p);
int i=0,j=0;
next(P); // 预处理函数。
while(i<n)
{ if(T[i]==p[j])// 已经匹配j+1个字符,
{ if(j==m-1) return i-j; //匹配成功返回匹配位置。
j++;i++; //比较下一个位置。
}
else { if(j>0) j=next[j-1] //失配,移动到部分匹配串。
else i++; // 失配。匹配串的首字符移动到目标串的当前位置
}
}
return -1;
}
http://www.cnblogs.com/kwklover/archive/2007/08/18/834853.html