BM算法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_NUM_CHAR 256

int *makeSkip(char *pcPatternStr)
{
    int  iCnti;
    int  iPatternLen = strlen(pcPatternStr);
    int *piSkip = (int*)malloc(MAX_NUM_CHAR * sizeof(int));

    /* 初始化MAX_NUM_CHAR个可能的字母的坏字符的跳跃长度都是iPatternLen + 1 */
    for (iCnti = 0; iCnti < MAX_NUM_CHAR; iCnti++)
    {
        piSkip[iCnti] = iPatternLen + 1;
    }

    while(0 != iPatternLen)
    {
        piSkip[(unsigned char) *pcPatternStr++] = iPatternLen--;
    }

    return piSkip;
}

int *makeShift(char *pcPatternStr)
{
    int   iPatternLen = strlen(pcPatternStr);
    int  *piShift     = (int *) malloc(iPatternLen * sizeof(int)); 
    int  *piShiftPtr  = piShift + iPatternLen - 1;    /* 作为piShift的一个副本,方便后面的操作 */
    char *piSrcEnd = pcPatternStr + iPatternLen - 1;  /* 作为好后缀参照的字符串的边界 */
    char  cLastCH;
	
	cLastCH = pcPatternStr[iPatternLen - 1];
	
    *piShiftPtr = 1;
	
    while(piShiftPtr-- != piShift)
    {
        char *piLastHead = pcPatternStr + iPatternLen - 2;
        char *piSrcTail;   /* 指向好后缀参照的字符串,和piLastTail成对出现,用来比较二者指向的字符是否相等 */
        char *piLastTail;  /* 指向最后的一个好后缀 */

        do
        {
            /* 空循环用来查找好后缀 */
            while((piLastHead >= pcPatternStr) && (*piLastHead-- != cLastCH));
			
            piSrcTail = pcPatternStr + iPatternLen - 2;
            piLastTail  = piLastHead;
			
            /* 遍历一个好后缀 */
            while((piLastTail >= pcPatternStr) 
                && (*piLastTail-- == *piSrcTail--) 
                && (piSrcTail >= piSrcEnd));
        }while((piLastTail >= pcPatternStr) && (piSrcTail >= piSrcEnd)); /* 查找最后一个好后缀 */
		
        /* piShift + iPatternLen - piShiftPtr 是主串在匹配串中往回走的长度,
           piSrcTail - piLastTail 是好后缀和参照字符串的跨度长度 */
        *piShiftPtr = (piShift + iPatternLen - piShiftPtr) + (piSrcTail - piLastTail);
		
        piSrcEnd--;  /* 参照字符串的边界后移一位 */
    }
	
    return piShift;
}

int iBMSearch(const char *pcTextStr, const char *pcPatternStr, int *piSkip, int *piShift)
{
    int iTextLen = strlen(pcTextStr);
    int iPatternLen = strlen(pcPatternStr);

	int iFindIndex = iPatternLen;
	
    if(iPatternLen == 0)
    {
        return 0;
    }
	
    while(iFindIndex <= iTextLen)
    {
        int iPatternTempLen = iPatternLen;
        int iSkipStride;  /* 坏字符串跳转长度 */
        int iShiftStride; /* 好后缀跳转长度 */
		
        while(pcTextStr[--iFindIndex] == pcPatternStr[--iPatternTempLen])
        {
            if(iFindIndex < 0)
            {
                return 1;
            }
			
            if(iPatternTempLen == 0)
            {
                return iFindIndex;
            }
        }
		
        iSkipStride = piSkip[(unsigned char) pcTextStr[iFindIndex]];
        iShiftStride = piShift[iPatternTempLen];
		/* 取iSkipStride和iShiftStride的大者作为跳转长度 */
        iFindIndex += (iSkipStride > iShiftStride) ? iSkipStride : iShiftStride;
    }
	
    return 1;
}


int main(void)
{
	char *pcTextStr = "hijkabacba";
	char *pcPatternStr = "ba";

    int *piShift;
    int *piSkip;
    int  iRet;

	piShift=makeShift(pcPatternStr);
    piSkip=makeSkip(pcPatternStr); 

    iRet = iBMSearch(pcTextStr, pcPatternStr, piSkip, piShift);
	printf("%d\n", iRet);

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值