如下是網上找來的,我整理了下,我的以爲寫的挺好的,分享給你們。web
1、介紹
BM算法:是一種精確字符串匹配算法,其基本思路採用從右向左比較的方法,其中用到了「壞字符規則」和「好後綴規則」,經過這兩個規則來決定向右跳躍的距離。算法
2、算法流程
BM算法的基本流程:設文本串T,模式串爲P。先將T、P左對齊,而後從右往左依次逐個字符比較,若是發現不匹配,則使用前面提到的兩個規則來計算獲得跳躍的距離,
一直到匹配結束或者匹配成功。ide
3、概念介紹
在匹配中已經匹配的部分稱爲好後綴,第一個不匹配的字符成爲壞字符。
1).壞字符規則
在BM算法從右向左掃描的過程當中,若發現某個字符x不匹配,則按以下兩種狀況討論: 函數
i. 若是字符x在模式P中沒有出現,那麼從字符x開始的m個文本顯然不可能與P匹配成功,直接所有跳過該區域便可。 性能
ii. 若是x在模式P中出現,則以該字符進行對齊。 spa
用數學公式表示,設Skip(x)爲P右移的距離,m爲模式串P的長度,max(x)爲字符x在P中最右位置。 orm
2).好後綴規則
若發現某個字符不匹配的同時,已有部分字符匹配成功,則按以下兩種狀況討論: blog
i. 若是在P中位置t處已匹配部分P'在P中的某位置t'也出現,且位置t'的前一個字符與位置t的前一個字符不相同,則將P右移使t'對應t方纔的所在的位置。 ip
ii. 若是在P中任何位置已匹配部分P'都沒有再出現,則找到與P'的後綴P''相同的P的最長前綴x,向右移動P,使x對應方纔P''後綴所在的位置。 ci
用數學公式表示,設Shift(j)爲P右移的距離,m爲模式串P的長度,j 爲當前所匹配的字符位置,s爲t'與t的距離(以上狀況i)或者x與P''的距離(以上狀況ii)。
在BM算法匹配的過程當中,取SKip(x)與Shift(j)中的較大者做爲跳躍的距離。
4、代碼實現
-
-
-
-
-
-
-
-
-
- int* MakeSkip(char *ptrn, int pLen)
- {
- int i;
-
-
-
- int *skip = (int*)malloc(256*sizeof(int));
-
- if(skip == NULL)
- {
- fprintf(stderr, "malloc failed!");
- return 0;
- }
-
-
- for(i = 0; i < 256; i++)
- {
- *(skip+i) = pLen;
- }
-
-
- while(pLen != 0)
- {
- *(skip+(unsigned char)*ptrn++) = pLen--;
- }
-
- return skip;
- }
-
-
-
-
-
-
-
-
-
-
-
- int* MakeShift(char* ptrn,int pLen)
- {
-
- int *shift = (int*)malloc(pLen*sizeof(int));
- int *sptr = shift + pLen - 1;
- char *pptr = ptrn + pLen - 1;
- char c;
-
- if(shift == NULL)
- {
- fprintf(stderr,"malloc failed!");
- return 0;
- }
-
- c = *(ptrn + pLen - 1);
-
- *sptr = 1;
-
- pptr--;
-
- while(sptr-- != shift)
- {
- char *p1 = ptrn + pLen - 2, *p2,*p3;
-
-
- do{
- while(p1 >= ptrn && *p1-- != c);
-
- p2 = ptrn + pLen - 2;
- p3 = p1;
-
- while(p3 >= ptrn && *p3-- == *p2-- && p2 >= pptr);
-
- }while(p3 >= ptrn && p2 >= pptr);
-
- *sptr = shift + pLen - sptr + p2 - p3;
-
-
-
-
-
-
-
- pptr--;
- }
-
- return shift;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- int BMSearch(char *buf, int blen, char *ptrn, int plen, int *skip, int *shift)
- {
- int b_idx = plen;
- if (plen == 0)
- return 0;
- while (b_idx <= blen)
- {
- int p_idx = plen, skip_stride, shift_stride;
- while (buf[--b_idx] == ptrn[--p_idx])
- {
- if (b_idx < 0)
- return -1;
- if (p_idx == 0)
- {
- return b_idx ;
- }
- }
- skip_stride = skip[(unsigned char)buf[b_idx]];
- shift_stride = shift[p_idx];
- b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;
- }
- return -1;
- }