BM模式比對演算法-實現(C語言)

來源:互聯網
上載者:User

原文地址:http://ouyangjia7.javaeye.com/blog/353137

#include "messageFormat.h"
#include <iostream>

using namespace std;

/*int processFile();
{

}*/

/*
函數:int* MakeSkip(char *, int)
目的:根據壞字元規則做預先處理,建立一張壞字元表
參數:
ptrn => 模式串P
PLen => 模式串P長度
返回:
int* - 壞字元表
*/
int* MakeSkip(char *ptrn, int pLen)

 int i;
 //為建立壞字元表,申請256個int的空間
 /*PS:之所以要申請256個,是因為一個字元是8位,
 所以字元可能有2的8次方即256種不同情況*/
 int *skip = (int*)malloc(256*sizeof(int));

 if(skip == NULL)
 {
  fprintf(stderr, "malloc failed!");
  return 0;
 } 

 //初始化壞字元表,256個單元全部初始化為pLen
 for(i = 0; i < 256; i++)
 {
  *(skip+i) = pLen;
 }

 //給表中需要賦值的單元賦值,不在模式串中出現的字元就不用再賦值了
 while(pLen != 0)
 {
  *(skip+(unsigned char)*ptrn++) = pLen--;
 }

 return skip;
}

/*
函數:int* MakeShift(char *, int)
目的:根據好尾碼規則做預先處理,建立一張好尾碼表
參數:
ptrn => 模式串P
PLen => 模式串P長度
返回:
int* - 好尾碼表
*/
int* MakeShift(char* ptrn,int pLen)
{
 //為好尾碼表申請pLen個int的空間
 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;//以最後一個字元為邊界時,確定移動1的距離

 pptr--;//邊界移動到倒數第二個字元(這句是我自己加上去的,因為我總覺得不加上去會有BUG,大家試試“abcdd”的情況,即末尾兩位重複的情況)

 while(sptr-- != shift)//該最外層迴圈完成給好尾碼表中每一個單元進行賦值的工作
 {
  char *p1 = ptrn + pLen - 2, *p2,*p3;

  //該do...while迴圈完成以當前pptr所指的字元為邊界時,要移動的距離
  do{
   while(p1 >= ptrn && *p1-- != c);//該空迴圈,尋找與最後一個字元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所在字元為邊界時,要移動的位置
  /*
  PS:在這裡我要聲明一句,*sptr = (shift + pLen - sptr) + p2 - p3;
  大家看被我用括弧括起來的部分,如果只需要計算字串移動的距離,那麼括弧中的那部分是不需要的。
  因為在字串自左向右做匹配的時候,指標是一直向左移的,這裡*sptr儲存的內容,實際是指標要移動
  距離,而不是字串移動的距離。我想SNORT是出於效能上的考慮,才這麼做的。   
  */

  pptr--;//邊界繼續向前移動
 }

 return shift;
}

/*
函數:int* BMSearch(char *, int , char *, int, int *, int *)
目的:判斷文本串T中是否包含模式串P
參數:
buf => 文本串T
blen => 文本串T長度
ptrn => 模式串P
PLen => 模式串P長度
skip => 壞字元表
shift => 好尾碼表
返回:
int - 1表示成功(文本串包含模式串),0表示失敗(文本串不包含模式串)。
*/
bool BMSearch(char *ptrn,char *buf)
{
 int plen = strlen(ptrn);
 int b_idx = plen; 
 int blen = strlen(buf);
 

 if (plen == 0)
  return false;
 
 int *skip  = MakeSkip(ptrn,plen);
 int *shift = MakeShift(ptrn,plen);

 while (b_idx <= blen)//計算字串是否匹配到了盡頭
 {
  int p_idx = plen, skip_stride, shift_stride;
  while (buf[--b_idx] == ptrn[--p_idx])//開始匹配
  {
   if (b_idx < 0)
    return false;
   if (p_idx == 0)
   {    
    return true;
   }
  }
  skip_stride = skip[(unsigned char)buf[b_idx]];//根據壞字元規則計算跳躍的距離
  shift_stride = shift[p_idx];//根據好尾碼規則計算跳躍的距離
  b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;//取大者
 }
 return false;
}
int main()
{
 char *ptr = "465789";
 char *buf = "789456465789";

 if ( BMSearch(ptr,buf) )
 {
  cout<<"find OK"<<endl;
 }
 
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.