假设长字符串为t
,短字符串为p
。为了进行KMP
匹配,首先需要计算字符串p
的next
数组,后面实现了计算该数组的函数void KmpGenNext(char* p, int* next)
。对于”abcabcab
”,计算出的next
数组如下图:
其中:next[i]
给出如下信息:从左到右将p
的字符与t
的字符进行比对时,若在p
的i
号位置出现不匹配,就将字符串p
相对t
右移i-next[i]
位;若next[i]>=0
,则右移后比对位置从next[i]
号位置开始,否则从0
号位置开始。下图给出了一个匹配示例。
核心算法代码如下:
#include <stdio.h> #include <stdlib.h> void KmpGenNext(char* p, int* next) //生成p的next数组, next数组长度大于等于字符串p的长度加1 { int i=0,lp; while(p[i]) i++; lp=i; i=0; next[0]=-1; int j=0; while(i<lp){ if(j==0||p[i]==p[j]){ i++; j++; next[i]=0; } else{ next[i]=-1; } } } int KmpFindSubWithNext(char* t, char* p, int* next) //从t中查找子串p的第一次出现的位置 //若找到,返回出现的位置,否则返回-1 { int i=0, j=0; while(p[i]!=0 && t[j]!=0) { if(p[i]==t[j]) { i++; j++; } else if (next[i]>=0) { i = next[i]; } else { i=0; j++; } } if(p[i]==0) return j-i; //found else return -1; //not found } int main() { char t[20],p[20]; int next[20]; printf("请输入主串:"); scanf("%s",t); printf("请输入要测试的子串:"); scanf("%s",p); int flag; KmpGenNext(p,next); flag = KmpFindSubWithNext(t,p,next); if(flag ==-1) printf("not found!\n"); else printf("匹配成功!匹配位置为 %d\n",flag); return 0; }