朴素模式匹配算法的缺点:当某些子串与模式串能部分匹配时,主串的扫描指针i经常回溯,导致时间开销增加
改进思路:主串指针不回溯,只有模式串指针回溯

求模式串的next数组:当模式串的第j个字符匹配失败时,令模式串跳到next[j]再继续匹配
串的前缀:包含第一个字符,且不包含最后一个字符的子串
串的后缀:包含最后一个字符,且不包含第一个字符的子串
手写求next:


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include<stdio.h> #include<stdlib.h> #include<stdbool.h>
#define MAXIEN 255 //预定义最大串长为255
typedef struct{ char ch[MAXIEN]; //每个分量存储一个字符 int length; //串的实际长度 }SString;
//求模式串T的next数组 void get_next(SString *T,int next[]){ int i=1,j=0; next[1]=0; while(i<T->length){ if(j==0 || T->ch[i] == T->ch[j]){ ++i; ++j; //若pi=pj,则next[j+1]=next[j]+1 next[i]=j; } else{ //否则令j=next[j],循环继续 j=next[j]; } } }
//KMP算法代码【平均时间复杂度O(n+m)】 int Index_KMP(SString *S,SString *T){ int i=1,j=1; int next[T->length+1]; get_next(T, next); //求模式串的next数组 while(i<=S->length && j<=T->length){ if(j==0 || S->ch[i] == T->ch[i]){ ++i; ++j; //继续比较后继字符 }else{ j=next[j]; //模式串向右移动 } } if(j>T->length){ return i-T->length; //匹配成功 }else{ return 0; } }
int main(){ SString S; }
|
KMP算法存在的问题:多进行了一次无意义的对比
KMP算法进一步优化:nextval数组
