bm算法

来源:互联网 发布:淘宝新手推广 编辑:程序博客网 时间:2024/04/28 05:09
  • /* 
  •  
  •   函数:void BuildBadCharacterShift(char *, int, int*) 
  • 目的:根据好后缀规则做预处理,建立一张好后缀表 
  • 参数:   
  • pattern => 模式串P   
  • plen => 模式串P长度      
  • shift => 存放坏字符规则表,长度为的int数组       
  • 返回:void            
  • */  
  • void BuildBadCharacterShift(char const* pattern, int plen, int* shift)  
  • {  
  •     forint i = 0; i < 256; i++ )     
  •         *(shift+i) = plen;  
  •     while ( plen >0 )          
  •     {     
  •         *(shift+(unsigned char)*pattern++) = --plen;          
  •     }     
  • }  
    1. /*! int search_badcharacter(char const*, int, char const*, int) 
    2.  
    3.   */bref 查找出模式串patn在主串src中第一次出现的位置  
    4.     
    5.     */return patn在src中出现的位置,当src中并没有patn时,返回-1  
    6.       
    7. */  
    8. int search_badcharacter(char const* src, int slen, char const* patn, int plen, int* shift)  
    9. {     
    10.     int s_idx = plen, p_idx;    
    11.     int skip_stride;      
    12.     if (plen == 0)        
    13.         return -1;  
    14.     while (s_idx <= slen)//计算字符串是否匹配到了尽头   
    15.     {     
    16.         p_idx = plen;     
    17.         while (src[--s_idx] == patn[--p_idx])//开始匹配       
    18.         {     
    19.             //if (s_idx < 0)   
    20.             //Return -1;      
    21.             if (p_idx == 0)       
    22.             {             
    23.                 return s_idx;         
    24.             }     
    25.         }  
    26.         skip_stride =  shift[(unsigned char)src[s_idx]];  
    27.         s_idx += (skip_stride>plen-p_idx ? skip_stride: plen-p_idx)+1;     
    28.     }     
    29.     return -1;    
    30. }  
    1. /* 
    2.   函数:void BuildGoodSuffixShift(char *, int, int*)  
    3. 目的:根据最好后缀规则做预处理,建立一张好后缀表     
    4. 参数: 
    5. pattern => 模式串P 
    6. plen => 模式串P长度 
    7. shift => 存放最好后缀表数组 
    8. 返回:void 
    9. */  
    10. void  BuildGoodSuffixShift(char const* pattern, int plen, int* shift)  
    11. {     
    12.     shift[plen-1] = 1;            // 右移动一位    
    13.     char end_val = pattern[plen-1];  
    14.     char const* p_prev, const* p_next, const* p_temp;  
    15.     char const* p_now = pattern + plen - 2;            // 当前配匹不相符字符,求其对应的shift  
    16.     bool isgoodsuffixfind = false;                    // 指示是否找到了最好后缀子串,修正shift值  
    17.     forint i = plen -2; i >=0; --i, --p_now)         
    18.     {     
    19.         p_temp = pattern + plen -1;   
    20.         isgoodsuffixfind = false;  
    21.         while ( true )        
    22.         {         
    23.             while (p_temp >= pattern && *p_temp-- != end_val);          // 从p_temp从右往左寻找和end_val相同的字符子串    
    24.             p_prev = p_temp;       // 指向与end_val相同的字符的前一个     
    25.             p_next = pattern + plen -2;             // 指向end_val的前一个  
    26.             // 开始向前匹配有以下三种情况      
    27.             //第一:p_prev已经指向pattern的前方,即没有找到可以满足条件的最好后缀子串  
    28.             //第二:向前匹配最好后缀子串的时候,p_next开始的子串先到达目的地p_now,   
    29.             //需要判断p_next与p_prev是否相等,如果相等,则继续住前找最好后缀子串     
    30.             //第三:向前匹配最好后缀子串的时候,p_prev开始的子串先到达端点pattern, 这个可以算是最好的子串  
    31.                     
    32.             if( p_prev < pattern  && *(p_temp+1) != end_val )         // 没有找到与end_val相同字符      
    33.                 break;  
    34.   
    35.             bool  match_flag = true;        //连续匹配失败标志    
    36.             while( p_prev >= pattern && p_next > p_now )        
    37.             {  
    38.                 if( *p_prev --!= *p_next-- )          
    39.                 {     
    40.                     match_flag = false;      //匹配失败   
    41.                     break;    
    42.                 }  
    43.             }  
    44.           
    45.             if( !match_flag )  
    46.                 continue;          //继续向前寻找最好后缀子串  
    47.             else      
    48.             {     
    49.                 //匹配没有问题, 是边界问题  
    50.                 if( p_prev < pattern || *p_prev != *p_next)    
    51.                 {  
    52.                     // 找到最好后缀子串  
    53.                     isgoodsuffixfind = true;  
    54.                     break;    
    55.                 }  
    56.                 // *p_prev == * p_next  则继续向前找    
    57.             }     
    58.         }  
    59.         shift[i] = plen - i + p_next - p_prev;  
    60.         if( isgoodsuffixfind )  
    61.             shift[i]--;               // 如果找到最好后缀码,则对齐,需减修正  
    62.     }  
    63. }  

     

    1. /*! int search_goodsuffix(char const*, int, char const*, int) 
    2.  
    3.   */bref 查找出模式串patn在主串src中第一次出现的位置  
    4.     
    5.     */return patn在src中出现的位置,当src中并没有patn时,返回-1  
    6.       
    7. */  
    8. int search_goodsuffix(char const* src, int slen, char const* patn, int plen, int* shift)  
    9. {  
    10.     int s_idx = plen, p_idx;    
    11.     int skip_stride;  
    12.     if (plen == 0)    
    13.         return -1;  
    14.       
    15.     while (s_idx <= slen)//计算字符串是否匹配到了尽头   
    16.     {     
    17.         p_idx = plen;  
    18.         while (src[--s_idx] == patn[--p_idx])//开始匹配   
    19.         {     
    20.             //if (s_idx < 0)   
    21.                 //return -1;  
    22.             if (p_idx == 0)   
    23.             {         
    24.                 return s_idx;     
    25.             }  
    26.         }  
    27.         skip_stride =  shift[p_idx];  
    28.         s_idx += skip_stride +1;  
    29.     }  
    30.     return -1;  
    31. }  

     

    1. /* 
    2. 函数:int* BMSearch(char *, int , char *, int, int *, int *) 
    3. 目的:判断文本串T中是否包含模式串P 
    4. 参数: 
    5. src => 文本串T 
    6. slen => 文本串T长度 
    7. ptrn => 模式串P 
    8. pLen => 模式串P长度 
    9. bad_shift => 坏字符表 
    10. good_shift => 最好后缀表 
    11. 返回: 
    12. int - 1表示匹配失败,否则反回                     
    13. */  
    14. int BMSearch(char const*src, int slen, char const*ptrn, int plen, int const*bad_shift, int const*good_shift)  
    15. {  
    16.     int s_idx = plen;    
    17.     if (plen == 0)    
    18.         return 1;  
    19.       
    20.     while (s_idx <= slen)//计算字符串是否匹配到了尽头   
    21.     {     
    22.         int p_idx = plen, bad_stride, good_stride;    
    23.         while (src[--s_idx] == ptrn[--p_idx])//开始匹配       
    24.         {         
    25.             //if (s_idx < 0)   
    26.                 //return -1;  
    27.               
    28.             if (p_idx == 0)       
    29.             {         
    30.                 return s_idx;     
    31.             }     
    32.         }  
    33.           
    34.         // 当匹配失败的时候,向前滑动  
    35.         bad_stride = bad_shift[(unsigned char)src[s_idx]];      //根据坏字符规则计算跳跃的距离  
    36.         good_stride = good_shift[p_idx];                                 //根据好后缀规则计算跳跃的距离  
    37.         s_idx += ((good_stride > bad_stride) ? good_stride : bad_stride )+1;//取大者      
    38.     }  
    39.     return -1;    
    40. }  
    0 0
    原创粉丝点击