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