Boyer-Moore 精确匹配算法实现(C/C++)

算法原理这里不废话,网上找到的算法很多再临界情况的处理都有错误,所以自己重写了一个。

预处理创建shift资源表时的效率比较一般,但是简单易懂! 如果你有更好的版本希望发来研究研究。


/*
 * Boyer-Moore 精确匹配算法
 * -------------------------------------------
 * copyright (c) 2012 Niu Chenguang <chrisniu1984@gmail.com>
 *
 * file: bm.h
 */

#ifndef __BM_H__
#define __BM_H__

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

#define BM_SKIP_SIZE    256
#define BM_SHIFT_SIZE   128 // 此值决定字串最大长度

/*
 * 为已知字符串创建skip资源表。
 *
 * @skip: [in/out] 存储skip资源的int数组。元素数必须为BM_SIKP_SIZE个。
 * @sub: [in] 已知字符串
 * @sub_len: [in] 字符串长度
 *
 * @RETURN: 0 = 成功,-1 = 失败
 */
static inline int bm_make_skip(int skip[], unsigned char *sub, int sub_len)
{
    if (NULL == skip || NULL == sub || sub_len <= 0) {
        return -1;
    }

    memset(skip, 0x00, sizeof(int)*BM_SKIP_SIZE);

    int i;
    for (i=0; i<BM_SKIP_SIZE; i++) {
        skip[i] = sub_len;
    }

    while (sub_len != 0) {
        skip[*sub] = --sub_len;
        sub++;
    }

    return 0;
}

/*
 * 为已知字符串创建shift资源表。
 *
 * @shift: [in/out] 存储shift资源的int数组。元素数必须为BM_SHIFT_SIZE个。
 * @sub: [in] 已知字符串
 * @sub_len: [in] 字符串长度
 *
 * @RETURN: 0 = 成功,-1 = 失败
 */
static inline int bm_make_shift(int shift[], unsigned char* sub,int sub_len)
{
    if (NULL == shift || NULL == sub ||
        sub_len <= 0 || sub_len > BM_SHIFT_SIZE) {
        return -1;
    }
    memset(shift, 0x00, sizeof(int)*BM_SHIFT_SIZE);

    int pos;
    for (pos = sub_len-1; pos >= 0; pos--) {
        //int i=0;
        //printf("---------------------\n");
        //printf("%s\n", sub);
        //for (i=0; i<pos; i++) {
        //    printf(" ");
        //}
        //printf("%s\n", sub+pos);

        unsigned char *good = sub + pos + 1; // 好后缀起始位置。
        int good_len = sub_len - pos - 1;  // 好后缀长度

        // 此循环是为了匹配到尽量长的好后缀串
        while (good_len > 0) {

            // p 为开始位置查找好后缀
            unsigned char *p = sub + sub_len - 1 - good_len;

            // 此循环是为了从右向左逐个位置查找好后缀串。
            while (p >= sub) {
                // 在p位置找到了good
                if (memcmp(p, good, good_len) == 0) {
                    shift[pos] = (sub_len-pos)+(good-p)-1;
                    break;
                }

                // 向左移动一个位置,准备继续查找good串
                p--;
            }

            // 此shift位置有值,说明查找成功,直接break
            if (shift[pos] != 0) {
                break;
            }

            // 取好后缀的子串
            good++;
            good_len--;
        }

        // 此shift位置没有值,说明没有匹配到good串及其字串
        if (shift[pos] == 0) {
            shift[pos] = sub_len-pos;
        }

        //for(i=0;i<shift[pos]-(sub_len-pos);i++){
        //    printf(" ");
        //}
        //printf("%s\n", sub);
    }

    return 0;
}

static inline int bm_search(unsigned char *str, int str_len,
                         unsigned char *sub, int sub_len,
                         int skip[], int shift[])
{
    if (sub_len == 0) {
        return 1;   // 根据实际需要,修改这个返回值。
    }

    if (sub_len > str_len) {
        return 0;
    }

    int str_end = sub_len - 1;
    while (str_end <= str_len) {
        int sub_end = sub_len-1;

        while (str[str_end] == sub[sub_end]) {
            if (sub_end == 0) {
                return 1;
            }
            str_end--;
            sub_end--;
        }

        int skip_stride = skip[str[str_end]];
        int shift_stride = shift[sub_end];

        str_end += MAX(skip_stride,shift_stride);
    }

    return 0;
}

#endif // __BM_H__


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Boyer-Moore算法是一种在文本中搜索模式的有效算法,它使用一个简单的技巧来提高搜索效率。下面是一段C语言实现Boyer-Moore算法的代码:int BoyerMooreSearch(char *txt, char *pat) { int m = strlen(pat); int n = strlen(txt); int badchar[256]; /* 填充bad character array */ FillBadChar(pat, m, badchar); int s = 0; while (s <= (n - m)) { int j = m-1; /* 找到匹配的字符*/ while (j >= 0 && pat[j] == txt[s+j]) j--; /* 找到匹配的字符 */ if (j < 0) { /* 打印匹配的字符 */ printf("在位置 %d 匹配成功\n", s); s += (s+m < n)? m-badchar[txt[s+m]] : 1; } else s += max(1, j - badchar[txt[s+j]]); } return -1; } ### 回答2: Boyer-Moore算法是一种用于字符串匹配的高效算法,相比于传统的字符串匹配算法,它具有更快的速度和更少的比较次数。下面是在C语言实现Boyer-Moore算法的代码: ```c #include <stdio.h> #include <string.h> #define MAX_CHAR 256 // 计算字符串中每个字符出现的最后位置 void computeLastOccurence(char *pattern, int *lastOccurence) { int len = strlen(pattern); for(int i = 0; i < MAX_CHAR; i++) { lastOccurence[i] = -1; } for(int i = 0; i < len; i++) { lastOccurence[(int)pattern[i]] = i; } } // 实现Boyer-Moore算法 int boyerMoore(char *text, char *pattern) { int textLen = strlen(text); int patternLen = strlen(pattern); int lastOccurence[MAX_CHAR]; // 计算每个字符在pattern中最后出现的位置 computeLastOccurence(pattern, lastOccurence); int shift = 0; while(shift <= textLen - patternLen) { int j = patternLen - 1; // 从后往前匹配pattern和text while(j >= 0 && pattern[j] == text[shift + j]) { j--; } if(j < 0) { // 匹配成功,返回匹配的起始位置 return shift; } else { // 计算pattern向右移动的距离 int maxShift = j - lastOccurence[(int)text[shift + j]]; if(maxShift < 1) { maxShift = 1; } shift += maxShift; } } return -1; // 未找到匹配的位置 } int main() { char text[] = "ABABCABABDABABCABABCDE"; char pattern[] = "ABABCABABCDE"; int result = boyerMoore(text, pattern); if(result == -1) { printf("未找到匹配的位置\n"); } else { printf("匹配位置: %d\n", result); } return 0; } ``` 以上是Boyer-Moore算法C语言中的实现代码。该算法通过计算每个字符在模式串中最后出现的位置,从而优化了字符串匹配的效率。在主函数中,我们定义了一个文本串和模式串,并调用boyerMoore函数进行匹配。最终输出匹配的位置或未找到匹配的提示信息。 ### 回答3: 下面是一个使用Boyer-Moore算法的C代码示例: ```c #include <stdio.h> #include <string.h> #define MAX_CHARS 256 // 计算字符串中每个字符最右出现的位置 void calculateBadChar(char *str, int size, int badChar[MAX_CHARS]){ int i; for(i = 0; i < MAX_CHARS; i++){ badChar[i] = -1; } for(i = 0; i < size; i++){ badChar[(int)str[i]] = i; } } // Boyer-Moore算法 int boyerMoore(char *text, char *pattern){ int textSize = strlen(text); int patternSize = strlen(pattern); int badChar[MAX_CHARS]; calculateBadChar(pattern, patternSize, badChar); int shift = 0; while(shift <= (textSize - patternSize)){ int j = patternSize - 1; while(j >= 0 && pattern[j] == text[shift+j]){ j--; } if(j < 0){ return shift; }else{ shift += (j - badChar[(int)text[shift+j]]); } } return -1; } int main(){ char text[] = "ABABDABACDABABCABAB"; char pattern[] = "ABABCABAB"; int result = boyerMoore(text, pattern); if(result == -1){ printf("Pattern not found in the text\n"); }else{ printf("Pattern found at index: %d\n", result); } return 0; } ``` Boyer-Moore算法是一种用于字符串搜索的高效算法,根据Pattern中的字符在Text中的出现位置规律,跳过一些不需要再进行比较的字符,从而提高搜索效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值