#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxSize 50
typedef struct Str{
char ch[MaxSize+1];
int length;
}Str;
//KMP算法
void getNext(Str substr,int next[]){
int j=1;
next[1]=0;
int t =0;
while(j<substr.length){
if(t==0||substr.ch[j]==substr.ch[t]){
next[j+1]=t+1;
t++;
j++;
}
else{
t=next[t];
}
}
printf(" j ");
for(int i=1;i<=substr.length;i++){
printf("%d ",i);
}
printf("\n模式串: ");
for(int i=1;i<=substr.length;i++){
printf("%c ",substr.ch[i]);
}
printf("\nnext[]: " );
for(int i=1;i<=substr.length;i++){
printf("%d ",next[i]);
}
}
int KMP(Str str,Str substr){
int next[MaxSize];
getNext(substr,next);
int j=1;
int i=1;
while(i<=str.length&&j<=substr.length){
if(j==0||str.ch[i]==substr.ch[j]){
i++;
j++;
}else{
j=next[j];
}
}
if(j>substr.length) return i-substr.length;
else return 0;
}
//将next[]数组进行优化
void getNextVal(Str substr,int nextval[]){
int j=1;
nextval[1]=0;
int t=0;
while(j<substr.length){
if(t==0||substr.ch[j]==substr.ch[t]){
if(substr.ch[j+1]!=substr.ch[t+1]) nextval[j+1]=t+1;
else nextval[j+1]=nextval[t+1];
j++;
t++;
}else{
t=nextval[t];
}
}
printf("\n j ");
for(int i=1;i<=substr.length;i++){
printf("%d ",i);
}
printf("\n模式串: ");
for(int i=1;i<=substr.length;i++){
printf("%c ",substr.ch[i]);
}
printf("\nnextval[]: " );
for(int i=1;i<=substr.length;i++){
printf("%d ",nextval[i]);
}
}
int AdvanceKMP(Str str,Str substr){
int nextval[MaxSize];
getNextVal(substr,nextval);
int j=1;
int i=1;
while(i<=str.length&&j<=substr.length){
if(j==0||str.ch[i]==substr.ch[j]){
i++;
j++;
}else{
j=nextval[j];
}
}
if(j>substr.length) return i-substr.length;
else return 0;
}
int main(){
char str1[]=" ABABBBAAABABABBA";
char substr1[]=" ABABABB";
Str str;
Str substr;
printf("请输入主串(以0开头):");
scanf("%s",str.ch);
printf("请输入主串的长度:");
scanf("%d",&str.length);
printf("请输入模式串(以0开头):");
scanf("%s",substr.ch);
printf("请输入模式串的长度:");
scanf("%d",&substr.length);
int r=KMP(str,substr);
printf("\n在主串的第%d个位置",r);
int r2=AdvanceKMP(str,substr);
printf("\n在主串的第%d个位置",r2);
}
其中next[]数组可以改进,比如在如下这种情况:
在第五个位置发现不匹配时,在next[]数组中查到next[5]=4,需要返回到第四个位置查,若还是相等则需要继续查,在如图所示情况则需要继续查,知道查到位置1,所以有改进之处,在查到相等时,则直接返回到第一个位置(如图),需要改进的是next[]数组,其改进方法如下图:
代码运行截图: