之前网上看的若干算法,无非两个原则:坏字符原则、好后缀原则。按照算法所述实现了一个版本,但发现其效率还不如本文所述的实现方式。个人分析效率较低的原因可能是因为不断地向前找坏字符或者好后缀来确定跳跃距离导致的,不断的比对操作应该是影响效率的根源。

下面贴一段实现较简单的方法,感谢之前的领导磊哥,实现参照了他的代码。

PS:大概看了下ClamAV的BM实现,感觉很复杂。

 #define BM_TAB_LEN  (256)

 uint64_t *InitBMTab(const uint8_t *In_ui8Pattern, uint64_t In_ui64PattLen)
{
uint64_t *pui64RetVal = NULL; if (In_ui8Pattern == NULL || In_ui64PattLen == )
{
goto fun_ret;
} pui64RetVal = (uint64_t *)malloc(sizeof(uint64_t) * BM_TAB_LEN);
if (pui64RetVal == NULL)
{
goto fun_ret;
} for (uint16_t i = ; i < BM_TAB_LEN; i ++)
{
pui64RetVal[i] = In_ui64PattLen;
} for (uint64_t i = ; i < In_ui64PattLen; i ++)
{
pui64RetVal[In_ui8Pattern[i]] = In_ui64PattLen - i - ;
} fun_ret:
return pui64RetVal;
} int8_t ReBuildBMTab(uint64_t *Out_pui64BMJmpTab, const uint8_t *In_ui8Pattern, uint64_t In_ui64PattLen)
{
int8_t i8RetVal = ; if (Out_pui64BMJmpTab == NULL || In_ui8Pattern == NULL || In_ui64PattLen == )
{
i8RetVal = -;
goto fun_ret;
} for (uint16_t i = ; i < BM_TAB_LEN; i ++)
{
Out_pui64BMJmpTab[i] = In_ui64PattLen;
} for (uint64_t i = ; i < In_ui64PattLen; i ++)
{
Out_pui64BMJmpTab[In_ui8Pattern[i]] = In_ui64PattLen - i - ;
} fun_ret:
return i8RetVal;
} void ReleaseBMTab(uint64_t *Out_pui64BMJmpTab)
{
if (Out_pui64BMJmpTab != NULL)
{
free(Out_pui64BMJmpTab);
}
} uint64_t BMSearch(const uint64_t *In_pui64BMJmpTab, const uint8_t *In_pui8Pattern, uint64_t In_ui64PattLen,
const uint8_t *In_pui8Buf, uint64_t In_ui64BufLen)
{
uint64_t ui64RetVal = -;
uint64_t ui64EndIdx = ; if (In_pui64BMJmpTab == NULL || In_pui8Pattern == NULL
|| In_ui64PattLen == || In_pui8Buf == NULL || In_ui64BufLen ==
|| In_ui64BufLen < In_ui64PattLen)
{
goto fun_ret;
} ui64EndIdx = In_ui64PattLen - ;
do
{
if (In_pui64BMJmpTab[In_pui8Buf[ui64EndIdx]] != )
{
ui64EndIdx += In_pui64BMJmpTab[In_pui8Buf[ui64EndIdx]];
continue;
}
if (memcmp(In_pui8Pattern, In_pui8Buf + ui64EndIdx - In_ui64PattLen + , In_ui64PattLen) == )
{
ui64RetVal = ui64EndIdx - In_ui64PattLen + ;
goto fun_ret;
}
ui64EndIdx ++;
} while (ui64EndIdx < In_ui64BufLen); fun_ret:
return ui64RetVal;
}

实践中更高效、实现起来相对简单的基于末尾坏字符原则的BM算法实现的更多相关文章

  1. unittest中更高效的执行测试用例一个类只需要打开一次浏览器

    示例代码 baidu.py # _*_ coding:utf-8 _*_ import csv,unittest #导入csv模块 from time import sleep from seleni ...

  2. 微服务平台(Micro Service Platform : MSP)旨在提供一个集开发、测试、运维于一体的开发者专属平台,让开发者能快速构建或使用微服务,让开发更简单,让运维更高效。

    微服务平台(Micro Service Platform : MSP)旨在提供一个集开发.测试.运维于一体的开发者专属平台,让开发者能快速构建或使用微服务,让开发更简单,让运维更高效. MSP采用业界 ...

  3. 使jQuqer更高效的方法

    讨论 jQuery 和 javascript 性能的文章并不罕见.然而,本文我计划总结一些速度方面的技巧和我本人的一些建议,来提升你的 jQuery 和 javascript 代码.好的代码会带来速度 ...

  4. 在Dubbo中使用高效的Java序列化(Kryo和FST)

    在Dubbo中使用高效的Java序列化(Kryo和FST) 作者:沈理 文档版权:Creative Commons 3.0许可证 署名-禁止演绎 完善中…… TODO 生成可点击的目录 目录 序列化漫 ...

  5. 阿里巴巴 Kubernetes 应用管理实践中的经验与教训

    作者 | 孙健波(阿里巴巴技术专家).赵钰莹 导读:云原生时代,Kubernetes 的重要性日益凸显.然而,大多数互联网公司在 Kubernetes 上的探索并非想象中顺利,Kubernetes 自 ...

  6. 从 DevOps 到 Serverless:通过“不用做”的方式解决“如何更高效做”的问题

    作者 | 徐进茂(罗离) JAVA 开发工程师  导读:近年来,Serverless 一词越来越热,它已经逐渐成为了一种新型的软件设计架构.和 DevOps 概念提倡的是通过一系列工具和自动化的技术来 ...

  7. 更强、更稳、更高效:解读 etcd 技术升级的三驾马车

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 陈星宇(宇慕 ...

  8. 用好Java中的枚举真的没有那么简单

    1.概览 在本文中,我们将看到什么是 Java 枚举,它们解决了哪些问题以及如何在实践中使用 Java 枚举实现一些设计模式. enum关键字在 java5 中引入,表示一种特殊类型的类,其总是继承j ...

  9. K8s 如何提供更高效稳定的编排能力?K8s Watch 实现机制浅析

    关于我们 更多关于云原生的案例和知识,可关注同名[腾讯云原生]公众号~ 福利: ①公众号后台回复[手册],可获得<腾讯云原生路线图手册>&<腾讯云原生最佳实践>~ ②公 ...

随机推荐

  1. Spring Data JPA实体详解

    1. Spring Data JPA实体概述 JPA提供了一种简单高效的方式来管理Java对象(POJO)到关系数据库的映射,此类Java对象称为JPA实体或简称实体.实体通常与底层数据库中的单个关系 ...

  2. HDUOJ---(4708)Rotation Lock Puzzle

    Rotation Lock Puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  3. JavaScript 设计模式之单例模式

    一.单例模式概念解读 1.单例模式概念文字解读 单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象.在Ja ...

  4. Oracle角色、权限的一些常用视图

    ORACLE中数据字典视图分为3大类, 用前缀区别,分别为:USER,ALL 和 DBA,许多数据字典视图包含相似的信息. 1)USER_*:有关用户所拥有的对象信息,即用户自己创建的对象信息: 2) ...

  5.  RabbitMQ3.6.3集群搭建+HAProxy1.6做负载均衡

    目录 目录 1.基本概念 1.1.RabbitMQ集群概述 1.2.软件负载均衡器HAProxy 2.RabbitMQ的配置步骤 2.1.安装 Erlang.RabbitMQ 2.2.修改 /etc/ ...

  6. OAF_OAF控件系列5 - Train的实现(案例)

    2014-06-02 Created By BaoXinjian

  7. C语言sprintf与sscanf函数

    1.前言 我们经常涉及到数字与字符串之间的转换,例如将32位无符号整数的ip地址转换为点分十进制的ip地址字符串,或者反过来.从给定的字符串中提取相关内容,例如给定一个地址:http://www.bo ...

  8. 服务商域名DNS大全

    服务商域名DNS:  服务商 DNS服务器   常用DNS: 英文域名DNS 主DNS名称:ns11.xincache.com 辅DNS名称:ns12.xincache.com 说明:新网共有5组DN ...

  9. Unix lrzsz命令 上传本地文件到服务器 / 发送文件到客户端

    第三方教程:https://www.jb51.net/article/73690.htm 安装命令: $ yum install lrzsz 本地上传文件到服务器,如果是xshell,直接拖拽文件进入 ...

  10. 手机端上传图片及java后台接收和ajaxForm提交

    有很多微信开发的项目在手机端需要传图片,但是又不想调用微信的上传图片接口,于是采取了如下做法: 使用ajaxForm提交文件所需js:jquery.form.js 页面代码: <%@ page ...