KMP算法查找字符串
假设长字符串为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;
}