Boyer-Moore字符串搜索算法

Boyer-Moore字符串搜索算法

 在计算机科学里,Boyer-Moore字符串搜索算法是一种非常高效的字符串搜索算法。它由Bob Boyer和J Strother Moore设计于1977年。此算法仅对搜索目标字符串(关键字)进行预处理,而非被搜索的字符串。虽然Boyer-Moore算法的执行时间同样线性依赖于被搜索字符串的大小,但是通常仅为其它算法的一小部分:它不需要对被搜索的字符串中的字符进行逐一比较,而会跳过其中某些部分。通常搜索关键字越长,算法速度越快。它的效率来自于这样的事实:对于每一次失败的匹配尝试,算法都能够使用这些信息来排除尽可能多的无法匹配的位置。

 使用到的规则:(具体可在网上找一下)

 坏字符规则(Bad Character):未出现,跳被检索串长;出现,以最短距离跳到字符
 好后缀规则(Good Suffix):被匹配串中还有已匹配串,移到第二个已配的串;如果没有,移到被匹配串中的最大子串

 看代码吧,重点在注释(支持C环境,如果是OC环境,放执行到地方即可)

void table(char*); // 建立前进表
int search(int, char*, char*); // 搜寻关键字
void substring(char*, char*, int, int); // 取出子字串

int skip[256];

//主程序
char str_input[] = "asdfwewdfgw2332sssakwdkAasssAAaawdasdfss";
char str_key[] = "wd";
char tmp[80] = {'\0'};
int m, n, p;
m = strlen(str_input); //计算字串长度
n = strlen(str_key);
table(str_key);
p = search(n-1, str_input, str_key);//用n-1,如此可以对应数组的下标,n-1对应key的最后一个字符

while(p != -1) {
    substring(str_input, tmp, p, m);
    printf("%s\n", tmp);//打印从开始匹配的字符数组
    p = search(p+n+1, str_input, str_key); //再次进行搜索,看是不是还可以搜索到
    while (p != -1) {
        substring(str_input, tmp, p, m);
        printf("%s\n", tmp);//打印从开始匹配的字符数组
        p = -1;//结束吧,哈哈
    }
} 

//建立前进表
void table(char *key) {
    int k, n;
    n = strlen(key);
    for(k = 0; k <= 255; k++)
        skip[k] = n;//skip初始化,数组每个元素值为key的长度
    for(k = 0; k < n - 1; k++)//
        skip[key[k]] = n - k - 1;//被搜索串第k个字符所对应的跳跃字符数,这样以最右端的字符为准。如此以来,skip中保存的是“不连续”的一个数组。
}

//搜寻关键字
int search(int p, char* input, char* key) {
    int i, m, n;
    char tmp[80] = {'\0'};
    m = strlen(input);
    n = strlen(key);
    
    while(p < m) {
        substring(input, tmp, p-n+1, p);//p-n+1为key在input中起始字符下标,p对应末尾字符下标
        if(!strcmp(tmp, key)) // 比较两字串是否相同
            return p-n+1;//匹配到了!!!返回可匹配的input中下标
        p += skip[input[p]];//此次匹配失败,起始下标p右移,input[p]为经过匹配的最右字符,skip[input[p]]对应前面求出的key中根据该字符平移距离。如此,key整体右移skip[input[p]]距离,然后进行下一次匹配。
    }
    return -1;//终于还是匹配失败了
}

//取出子字串
void substring(char *text, char* tmp, int s, int e) {
    int i, j; 
    for(i = s, j = 0; i <= e; i++, j++) //截取input的一个子串,放到tmp中,这样tmp中就有数据了
        tmp[j] = text[i];
    tmp[j] = '\0'; 
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值