(可以转载,但请注明出处!)
下面是有关学习KMP的参考网站
http://blog.csdn.net/yaochunnian/article/details/7059486
http://blog.csdn.net/v_JULY_v/article/details/6111565
http://blog.csdn.net/v_JULY_v/article/details/6545192
http://blog.csdn.net/oneil_sally/article/details/3440784
http://billhoo.blog.51cto.com/2337751/411486
先说说next数组的含义:
next[i]就是前面长度为i的字符串前缀和后缀相等的最大长度,也即索引为i的字符失配时的前缀函数。
下面几个版本的next函数,除了next[0]不同外(版本一中为-1,版本二中为0),其余无差别
一:KMP算法模板
版本一:
//求str对应的next数组 void getNext(char const* str, int len) { int i = 0; next[i] = -1; int j = -1; while( i < len ) { if( j == -1 || str[i] == str[j] ) //循环的if部分 { ++i; ++j; //修正的地方就发生下面这4行 if( str[i] != str[j] ) //++i,++j之后,再次判断ptrn[i]与ptrn[j]的关系 next[i] = j; //之前的错误解法就在于整个判断只有这一句。 else next[i] = next[j]; //这里其实是优化了后的,也可以仍是next[i]=j //当str[i]==str[j]时,如果str[i]匹配失败,那么换成str[j]肯定也匹配失败, //所以不是令next[i]=j,而是next[i] = next[j],跳过了第j个字符, //即省去了不必要的比较 //非优化前的next[i]表示前i个字符中前缀与后缀相同的最大长度 } else //循环的else部分 j = next[j]; } } //在目标字符串target中,字符str出现的个数 //n为target字符串的长度,m为str字符串的长度 int kmp_match(char *target,int n,char *str,int m){ int i=0,j=0; //i为target中字符的下标,j为str中字符的下标 int cnt=0; //统计str字符串在target字符串中出现的次数 while(i<=n-1){ if(j<0||target[i]==str[j]){ i++; j++; } else{ j=next[j]; //当j=0的时候,suffix[0]=-1,这样j就会小于0,所以一开始有判断j是否小于0 } //str在target中找到匹配 if(j==m){ cnt++; j=next[j]; } } return cnt; } //在目标字符串target中,若存在str字符串,返回匹配成功的第一个字符的位置 int kmp_search(char *target,int n,char *str,int m){ int i=0,j=0; //i为target中字符的下标,j为str中字符的下标 int cnt=0; //统计str字符串在target字符串中出现的次数 while(i<n && j<m){ if(j<0||target[i]==str[j]){ i++; j++; } else{ j=suffix[j]; //当j=0的时候,suffix[0]=-1,这样j就会小于0,所以一开始有判断j是否小于0 } } if(j>=m) return i-m; else return -1; }