这两篇文章都写得很好,给我有很多帮助,但是看上面的源代码有一些地方我自己不理解,所以按照自己的思想改动了一些地方,现在将源代码贴下,我进行了简单的测试,全部正确,不过肯定测试的不完善,大家如果发现了错误请留言, 我好改正,大家对代码中有不明白的地方也可以留言,我可以帮忙说下,代码如下:#include
#include
#include
/*
函数:int* MakeSkip(char*,int)
母的:根据坏字符规则做预处理,建立一张坏字符表
表的长度由字符的规模而定,
如果只有字母则长度只有26,
如果是字母加数字长度就是26+10
参数:
ptrn=>模式串P
pLen=>模式串P长度
返回:
int* - 坏字符表
*/
int *MakeSkip(char* ptrn,int pLen)
{
int i;
int len=pLen;
char *p=ptrn;
//为建立坏字符表,申请256个int的空间
int *skip=(int*)malloc(256*sizeof(int));
if(skip==NULL)
{
printf("malloc failed!");
return 0;
}
//初始化坏字符表,256个单元全部初始化为pLen
for(i=0;i<256;i++)
{
*(skip+i)=pLen;
}
//赋值,从左到右遍历ptrn,这样如果一个字符出现两次,后面的覆盖前面的,
//不在模式中出现的字符不用再赋值,它们使用默认值pLen。
while(pLen!=0)
{
*(skip+(int)*ptrn++)=--pLen;
}
return skip;
}
/*
函数:int *MakeShift(char*,int)
目的:根据好后缀原则做预处理,建立一张好后缀表
参数:
ptrn=>模式串P
pLen=>模式串P的长度
返回:
int* :好后缀表
*/
int *MakeShift(char *ptrn,int pLen)
{
//为好后缀表申请pLen个int的空间
//这样,第一个位置放置长度为1的后缀
int *shift=(int *)malloc(pLen*sizeof(int));
int *sptr=shift+pLen-1;//方便为好后缀表进行赋值的指针
char *pptr=ptrn+pLen-1;//记录好后缀表边界位置的指针
char c;
//int i;
if(shift==NULL)
{
fprintf(stderr,"malloc failed!");
return 0;
}
c=*(ptrn+pLen-1);//保存模式串中最后一个字符,因为要反复用到它
*sptr=1;//以最后一个字符为边界时,移动距离设为1(因为要与坏字符规则比较,所以这个是个假设,1也是最小的移动距离)
pptr--;//边界移动到倒数第二个字符
while(--sptr>=shift)//该最外层循环完成给好后缀表中的每一个单元进行赋值的工作
{
char *p1=ptrn+pLen-2,*p2,*p3;
//该do...while循环完成以当前pptr所指向的字符为边界时,要移动的距离
do
{
while(p1>=ptrn&&*p1--!=c);//该空循环,寻找与最后一个字符c匹配的字符所指向的位置
if(p1
{
*sptr=pLen;
break;
}
p2=ptrn+pLen-2;
p3=p1;
while(p3>=ptrn&&*p3--==*p2--&&p2>=pptr);//该空循环,判断在边界内字符串匹配到什么位置
if(p2
{
if(*++p3==*++p2)
{
*sptr=p2-p3;
break;
}
if(*p2==*p3)
{
continue;
}
}
if(p3
{
*sptr=p2-p3;
break;
}
}while(p3>=ptrn);
pptr--;//边界继续向前移动
}
return shift;
}
/*
函数:int* BMSearch(char*,int ,char*,int,int*,int*)
目的:判断文本串是否包含模式串P
参数:
buf->文本串T
blen->文本串T长度
ptrn->模式串P长度
plen->模式串P长度
skip->坏字符表
shift->好后缀表
返回:
int->1表示成功(文本串包含模式串),0表示失败(文本串不包含模式串)
*/
int BMSearch(char *buf,int blen,char *ptrn,int plen,int *skip,int *shift)
{
int b_idx=plen;
if(plen==0)
{
return 1;
}
while(b_idx<=blen)//计算字符串是否匹配到了尽头
{
int p_idx=plen,skip_stride,shift_stride;
int i=0;
int temp=b_idx;//是为了不改动b_idx的值,b_idx将来用于计算移动的距离
while(buf[--temp]==ptrn[--p_idx])//开始匹配
{
i++;
if(p_idx==0)
{
fprintf(stderr,"match at %d!",b_idx);
return 1;
}
}
printf("i:%d/tbad:%c/n",i,buf[temp]);
skip_stride=skip[(unsigned char)buf[temp]]-i;//根据坏字符规则计算跳跃的距离
shift_stride=shift[p_idx];
printf("b_idx:%d 1:%d 2:%d/n",b_idx,skip_stride,shift_stride);
b_idx+=(skip_stride>shift_stride)?skip_stride:shift_stride;//取最大者
}
return 0;
}
int main()
{
char *buf="bcczcsabcd";
char *ptrn="abc";
int *skip=NULL;
int *shift=NULL;
fprintf(stderr,"plen=%d!/n",strlen(ptrn));
skip=MakeSkip(ptrn,strlen(ptrn));
shift=MakeShift(ptrn,strlen(ptrn));
BMSearch(buf,strlen(buf),ptrn,strlen(ptrn),skip,shift);
return 1;
}