kmp算法-字符串匹配
描述
主串为S,模式串为T,指针i和j指示主串S和模式串T中当前正待比较的字符位置。
KMP算法的思想
KMP算法就是从主串中找到与模式串完全匹配的位置。
从主串的第pos个字符起和模式串的第一个字符比较,若相等,则逐个比较后续字符
;否则每当一趟匹配过程中出现字符不等时,不需回溯i指针,而是利用已经得到的
“部分匹配”结果将模式串向右“滑动”尽可能远的一段距离继续比较。依次类推,
直至模式串中的每个字符依次和主串中的一个连续的字符序列相等,则匹配成功,
函数值为和模式串中第一个字符相等的字符在主串中的序号,否则匹配不成功,函
数值为0。
KMP算法的最大优点是减少字符串查找过程的回退,i指针不需要回溯。
模式匹配成功的条件是j>T[0]
匹配成功返回的值是i-T[0]
KMP算法的流程
假设主串为's1 s2...sn' ,模式串为'p1 p2...pn'
令i的初值为pos,j的初值为1,若在匹配过程中si=pj,则i和j分别增1,
否则i不变,而j退到next[j]的位置再比较,若相等,则指针各增1,
否则j再退到下一个next值的位置,依次类推,直至下列两种可能:
1.j退到某个next值s时字符比较相等,则指针各自增1,继续进行匹配
2.j退到值为0(即失配),则此时需将模式继续向右滑动一个位置,即从
主串的下一个字符s(i+1)起和模式串重新开始匹配。
注:匹配过程中产生“失配”时,指针i不变,指针j退回到next[j]所
指示的位置上重新进行比较,并且当指针j退回到0时指针i和指针j需
同时增1
next数组=最大公共前后缀个数+1
代码
#include<stdio.h>
#include<string.h>
int index_KMP(char *s,char *t,int pos);
//利用模式串的t的next函数求t在主串s中的第pos个位置之后的位置的KMP算法(t非空,1<=pos<=Strlength(s))。
void get_next(char * t,int * next);
//求模式串t的next函数的并存入数组next[]中。
char s[100];
char t[100];
int next[5];
int pos=0;
int index_KMP(char *s,char *t,int pos){
//利用模式串的T的NEXT函数求t在主串s中的第pos个位置之后的位置的KMP算法,(t非空,1<=pos<=Strlength(s)).
int i=pos,j=1;
while (i<=(int)strlen(s)&&j<=(int)strlen(t)){
if (j==0 || s[i]==t[j-1]){//继续进行后续字符串的比较
i++;
j++;
}
else{
j=next[j]; //模式串向右移动
}
}
if(j>(int)strlen(t)){//匹配成功
return i-strlen(t)+1;
}
else{//匹配不成功
return 0;
}
}
void get_next(char *t,int *next){
//求模式串t的next函数的并存入数组next[]中。
int i=1,j=0;
next[0]=next[1]=0;
while(i<(int)strlen(t)){
if(j==0 || t[i]==t[j]){
i++;
j++;
next[i]=j;
}
else{
j=next[j];
}
}
}
int main(){
printf("请输入字符串(主串):");
gets(s);
printf("请输入模式串:");
gets(t);
int n;
get_next(t,next);
n=index_KMP(s,t,pos);
if(n!=0){
printf("模式串t在主串s中第%d个位置起开始匹配\n",n);
}
else{
printf("主串中不存在与模式串相匹配的子串\n");
}
}