bm算法的c语言实现,BM算法C语言实现

这两篇文章都写得很好,给我有很多帮助,但是看上面的源代码有一些地方我自己不理解,所以按照自己的思想改动了一些地方,现在将源代码贴下,我进行了简单的测试,全部正确,不过肯定测试的不完善,大家如果发现了错误请留言, 我好改正,大家对代码中有不明白的地方也可以留言,我可以帮忙说下,代码如下:#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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值