串是一种特殊的线性表,其特殊性表现在数据元素是一个字符,也就是说,串是一种串是一种受限的线性表。既然是线性表,那么同样可以有顺序和链式两种结构,但是从总体来看,串在链式存储结构中,他占用存储量大且操作复杂,不如顺序存储结构灵活。串的模式匹配比较著名的有BF算法和KMP算法,下面就用这两种算法,实现模式匹配并计算next值和修正next值。因为有next值和修正next值,所以,KMP算法的用到两次。
【完整代码】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 225
//串的顺序储存结构
typedef struct
{
char ch[MAXLEN+1];
int length;
}SString;
int Index_BF(SString S,SString T,int pos)
{//返回模式T在主串S中第pos个字符开始第一次出现的位置。若不存在,则返回值为0
//其中,T非空,1<=pos<=S.length
int tag1=0;
int i=pos,j=0;
pos=0;
while(i<=S.length && j<=T.length) //两个串均未比较到串尾
{
if(S.ch[i]==T.ch[j]) //继续比较后继字符
{
++i;++j;
}
else
{
i=i-j+1;j=0; //指针后退重新开始匹配
}
tag1++;
}
if(j>T.length)
// return i-T.length;
printf("BF比较%d次 子串位置:%d\n",tag1-1,i-T.length);
else
//return 0;
printf("匹配失败\n");
}
int Index_KMP1(SString S,SString T,int next[])
{//利用模式串T的next函数求T在主串S中第pos个字符之后的位置 ,1<=pos<=S.length
int i=0,j=0;
int tag2=0;
// int next[MAXLEN+1];
while(i<=S.length && j<=T.length) //两个串均未比较到串尾
{
if(j==-1||S.ch[i]==T.ch[j])
{
++i;++j; //继续比较后继字符
}
else
j=next[j]; //模串向右移
tag2++;
}
if(j>T.length)
//return i-T.length;
printf("KMP1比较%d次 子串位置:%d\n",tag2-1,i-T.length);
else
//return 0;
printf("匹配失败");
}
int Index_KMP2(SString S,SString T,int next[])
{//利用模式串T的next函数求T在主串S中第pos个字符之后的位置 ,1<=pos<=S.length
int i=0,j=0;
int tag3=0;
while(i<=S.length && j<=T.length) //两个串均未比较到串尾
{
if(j==-1||S.ch[i]==T.ch[j])
{
++i;++j; //继续比较后继字符
}
else j=next[j]; //模串向右移
tag3++;
}
if(j>=T.length)
//return i-T.length;
printf("改进KMP比较%d次 子串位置:%d\n",tag3-1,i-T.length);
else
//return 0;
printf("匹配失败");
}
void get_next(SString T,int next[])
{
int i=0,j=-1;
next[0]=-1;
while(i<T.length)
{
if(j==-1||T.ch[i]==T.ch[j])
{
++i;++j;next[i]=j;
}
else j=next[j];
}
}
void get_nextval(SString T,int nextval[])
{
int i=0,j=-1;
nextval[0]=-1;
while(i<T.length)
{
if(j==-1||T.ch[i]==T.ch[j])
{
++i;++j;
if(T.ch[i]!=T.ch[j]) nextval[i]=j;
else nextval[i]=nextval[j];
}
else j=nextval[j];
}
}
int main()
{
int next[1000];
int nextval[1000];
int pos;
SString S,T; //S为主串,T为子串
printf("请输入主串:\n");
scanf("%s",S.ch);
S.length=strlen(S.ch);
printf("请输入子串:\n");
scanf("%s",T.ch);
T.length=strlen(T.ch);
Index_BF(S,T,pos);
get_next(T,next);
Index_KMP1(S,T,next);
get_nextval(T,nextval);
Index_KMP2(S,T,nextval);
return 0;
}
运行及试验结果: