KMP算法

    技术2024-11-22  17

    KMP算法i指针表示主串(被匹配串),j指针表示模式串首要确认next[]的值,决定匹配串要移动的距离举例说明:匹配串为S{abcac},主串(被匹配串)为P小标从0开始,(=?表示是否相等)next[0]=-1next[1]=0next[2],则看s[0]=?s[1],若相等,则next[2]=1,即看字符串S[2]前面是否有字串相等,字串{a}!={b},那么next[2]=0next[3],则看s[0]=?s[2],s[0,1]=?s[1,2],即看字符串S[3]前面是否有字串相等,next[3]的值为最大相等字串的长度,这里字串{a}!={b},{ab}!={bc},则next[3]=0next[4],则看s[0]=?s[3],s[0,1]=?s[2,3],s[0,1,2]=?s[1,2,3]是否有字串相等,next[4]取最大的字串长度,这里next[4]=1.KMP的优点在于被匹配的串指针不需要回溯,只需匹配串移动即可,没下一次匹配,将S[next[i]]的位置与被匹配串指针对应。若被匹配串为abcabacabcac,匹配过程为(i指针表示被匹配串,j指针表示匹配串):            abcac(下标从0开始),i=4,j=4时不匹配,next[4]=1,那下一次匹配s[1]即{b}将与i=4即{b}对应,即            abcabacabcac               abcaci=5,j=2时不匹配,next[2]=0,那么下一次匹配s[0]即{a}与i=5即{a}匹配,即            abcabacabcac                 abcaci=6,j=1时,不匹配,next[1]=0,那么下一次匹配s[0]即{a}与i=6即{c}匹配,即            abcabacabcac                  abcaci=6,j=0时,不匹配,next[0]=-1.那么下一次匹配            abcabacabcac                   abcac            匹配成功

    void getNext(char *s, int next[]) { int j,k,len; j = 0;k = -1;next[0] = -1; len = strlen(s); while(j<len-1) { if(k == -1 || s[j] == s[k]) { j++;k++; next[j] = k; } else k = next[k]; } }

    但是算法可以改进,改进之后即:比较S[j]和S[k],若不等,则 nextval[j]=next[j];若相等nextval[j]=nextval[k];(*)举例:(下标从0开始)        012345678   p:   aaabaaaab   s:   aaaabi=3,j=3时,不匹配,next[3]=2,常规KMP下一次匹配为P[3]对应S[2],但是s[2]=s[3],所以无需进行常规KMP的下一次匹配,跳到下下次的常规KMP匹配,即P[3]与s[1]对应匹配,但是s[1]=s[3],也无需进行,继续跳到下一次,实际上,因为模式中的第1、2、3个字符和第4个字符都相等,因此,不需要再和主串中第4个字符相比较,而可以将模式一次向右滑动4个字符的位置直接进行i=4,j=0时的字符比较。  代码实现如下(unix环境):   #include <stdio.h> #include <stdlib.h> #include <string.h> static int nextval[100]; void GetNextVal(char s[1024],int nextval[]) { int j,k,len; j = 0;k = -1; len = strlen(s); nextval[0] = -1; while(j < len-1) { if(k==-1 || s[j]==s[k]) { j++;k++; if(s[j]!=s[k]) nextval[j] = k; else nextval[j]= nextval[k]; } else k=nextval[k]; } } int KMPAdvance(char s[1024], char t[1024]) { int i=0, j=0, v; int len_s,len_t; len_s = strlen(s); len_t = strlen(t); GetNextVal(s,nextval); while(i < len_t && j < len_s) { if(j==-1 || t[i] == s[j]) { i++;j++; } else j = nextval[j]; } if(j>=len_s) v = 1;//匹配返回1 else v = -1; //不匹配返回-1 return v; } int main(int argc, char **argv) { char s[1024]; char t[1024]; int success; printf("请输入主串:"); scanf("%s", t); int len = strlen(t); printf("请输入模式串:"); scanf("%s", s); success = KMPAdvance(s, t); if(success == 1) printf("succeed!/n"); else printf("fail!/n"); return 0; }

    有疑问的人可以去看看李春葆的PPT,讲得还是很清楚的。

    最新回复(0)