思想:
快速模式匹配中最重要的是真前缀和真后缀的理解。
那么,什么是真前缀和真后缀呢?举个梨子吧:abcabcef,在这一串字符串中,abcabcef,带红色的b之前的最前面的字符a和最后面倒数第一个字符a相等,也就是紫色部分。依此类推,
ab
cabcefc前的紫色区域分别是真前缀和真后缀。
那么,真前缀真后缀有什么作用呢? 试想一下,当字符串c之前的所有字符都匹配,当移了一个位子之后,是不是就不匹配了呢!那么,下一次匹配是在什么时候呢?就是将真前缀的后一个字符对应的文本移到真后缀对应的文本的后一个字符。
所以,写出快速模式匹配第一步是计算每个字符的最大真前缀和真后缀的字符数。通常第一个字符设置为-1。
#include <stdio.h>
#include <stdlib.h>
# define maxsize 100
typedef struct{
char str[maxsize];
int length;
}seqstring;
// 获得真前缀真后缀
void getnext(seqstring p,int next[]) // 参数的作用,接受调用函数时传来的数据;
{
int i,j;
i=0;
j=-1;
next[0]=-1;
while(i<p.length)
{
if(j==-1 || p.str[i]==p.str[j])
{
++i;
++j;
next[i]=j; //当第二个条件不满足时,当前数的最大真前缀真后缀为0;
}
else
j=next[j]; // 将j置为-1,下一次进行if之内的循环。
}
for(i=0;i<p.length;i++)
printf("%5d",next[i]);
printf("\n");
}
// 快速模式匹配
int KMP(seqstring t,seqstring p,int next[])
{
int i=0,j=0;
while(i<t.length && j<p.length)
{
if(j==-1 || t.str[i]==p.str[j])
{
i++;
j++;
}
else
j=next[j];
}
if(j==p.length)
return (i-p.length) ;
else
return -1;
}
void creat(seqstring * t)
{
char ch;
int i=0;
printf("Please enter \n");
while ((ch=getchar())!='\n')
{
t->str[i++]=ch;
t->length++;
}
}
void init( seqstring *p)
{
p->length=0;
}
int main()
{
seqstring t,p;
int next[100];
int j;
init(&p);
init(&t);
creat(&t);
creat(&p);
getnext(p,next);
j=KMP(t,p,next);
printf("第%5d个时匹配",j);
return 0;
}