#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;
}