`
十三月的
  • 浏览: 164895 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

打破思维断层之令人惊叹的Shift-And/Or

阅读更多

令人惊叹的Shift-And/Shift-Or

目的Shift-And算法为载体,试图在减少思维断层情况下学习作者算法思想

目录

      1:主要思想

        2:算法介绍

   3:构建辅助表B

   4:容器创建和更新

   5:过程展示

   6: Shift-And VS KMP,展示Shift-And令人惊叹之处

   7:在KMP的基础上,揭示Shift-And的神器:位并行(精髓)

 

第一步:主要思想(可以先看第3-5步,更容易理解)

   Shift-And算法和KMP算法一样,是基于前缀来进行字符串匹配。但是它的算法思想要比KMP思路简单很多。它主要是维护了一个集合,该集合中保存的是所有既是模式串的前缀同时又是目标串的后缀的字符串。每次读入一个新的文本,本算法就利用位并行的方法更新该集合(神奇之处)。该集合用一个位掩码D进行表示:dm...d1表示(m表示的是模式串的大小)

第二步:算法介绍(可以先看第3-5步,更容易理解)

    D的第j位为1的时候(此时成Dj是活动的),表示模式串前缀的p1…pj同时也是目标串t1…ti后缀.而当dm是1的时候,表示有一个匹配成功。当读入目标串的下一个字符t(i+1)的时候,需要对D进行更新为D’当且仅当D的第j位是活动的,并且t(i+1)和p(j+1)相同的时候,此时可以利用位并行的方法在常数时间内对D进行更新。

第三步:构建辅助表B

   集合B记录模式串中每一个字符位掩码bm…b1.如果pj=x,则B[x]的第j为设为1.否则为0.

举例1:模式串announce共8位


 

 同理可以得到B(其中模式串中不包含的字符*设为00000000

 



 第四步:容器创建和更新

       对于容器D,初始化为000000000m :m位全为0.表示当前还没有即使模式串前缀又是目标串后缀。

       当读入一个新的目标串字符t(i+1),可以以如下公式进行更新。

 



 
第五步:过程展示

       下面是整个过程:目标串是’annual_announce’ 模式串announce


    
其实这个例子个人觉得并不是很理想,虽然它能说明情况,但是很难从这个例子的过程中体会到这个过程奇妙发生的根本所在。

 

例子2

 

目标串是cbcbcbaefd  模式串是cbcba

 

建表B


 
如果你看明白了,就会发现上述做法真的很奇妙。

5)步中,读取了c,但是模式串中的确实a,在没有读取c之前,结果是01010,这个的意思是模式串前4个字符前两个字符cb和前4个字符cbcb既是模式串的前缀,同时又是目标串的后缀。当读入第5个字符c后,经过更新D后变成了00101,这个结果表示前5个字符中,只有第1个字符c和前3个字符cbc既是模式串的前缀又是目标串的后缀

     这就是它的厉害之处,读入一个新的字符之后,经过这样3个步骤,就计算出来当前模式串前5个字符中所有的前缀(同时是目标串的后缀)。

 

      也许这样还表现不太明显,但是如果你很熟悉KMP算法,因为KMP的贡献在于它并不进行回溯同时很巧妙的利用迭代改变指针j。如果说kmp巧妙,它确实是,但是和Shift-And相比,真是小巫见大巫。因为kmp是用迭代,有可能需要迭代很多次,才能达到效果,此处只是一次位并行操作,就达到了kmp的效果。效率大大的提高。

 

第六步:Shift-And  VS  KMP,展示Shift-And令人惊叹之处

 KMP算法的精髓在于不回溯并采用巧妙的迭代方法得到next数组,将时间复杂度理论上降到了o(n)。 如果想清楚了解KMP,可以参考 http://wlh0706-163-com.iteye.com/blog/1843923

 

以下面这个案例再次进行分析

 


   
当第26个字符,cf匹配失败的时候,kmp使用的方法是:找到了模式串中前25个字符的所有的既是模式串的前缀同时又是目标串的后缀

 


 找到了这4对前缀 a,aca,acabaca,acabacabaca.

 


上图中第1步:由于最大的前缀acabacabaca的后面一个字符t和第26个字符c并不匹配,执行第2步。

上图中第2步:由于第二大的前缀acabaca(同时是最大前缀acabacabaca的最大前缀,这是kmp算法实施迭代技巧的的根本性质)后面的一个字符b和第26个字符c并不匹配,执行第3步。

上图中第3步同样面临这c和b不等的情况,执行第4步。

上图中第4步:由于前缀a后一个字符c和第26个字符相同,此时指向目标串的指针i= 26和执行模式串的指针j由原来的26经过一系列改变(1282)最终为2. 然后i++j++开始匹配下一个字符.

代码:



 (本段代码在上篇文章中有)

 

    然后再看一下shift-and算法是如何找到这个kmp进行了4次迭代才找到的第2位的c的。

此例中:

B[c] =

当比较完第25个字符之后

D  =  

(这个是根据D的定义结合上述图片展示的4对前缀写出来的)

运算过程:

 

 
只是一次运算就计算出了kmp中需要4次迭代才能计算出来的结果

那么Shift-And是如何需要1次就做到的KMP 算法4次才能做到的效果呢?下面来演示这个过程

第七步:KMP的基础上,揭示Shift-And的神器:位并行(精髓)

 

 

      再来看张图:其实这4步操作,目的只有一个,就是拿目标串的c和模式串的4对前缀的后一个字符相比较其他字符都不需要比较。即ctbbc相比较。

t,b,b,c的位置是什么?12842

再看看Shift-And中的D左移一位之后是什么呢?

   你可以清楚的看到上面的数字,奇妙之处就在这里。

 (注:26实际上已经比较过了,就是第1次比较cf

这个只是找到了要和c比较的位置,下一步就是比较这些位置是不是c,所以才有了shift-And算法中第三步:相与操作。即从容器B中提取出来c出现的所有的位置即位掩码B[c]



      
其实这里为什么能用相与操作呢?如果想要深入理解相与的妙处,可以先看一个简单的案例

http://wlh0706-163-com.iteye.com/blog/1393631  这里的c12842这些位置的比较实际相同或者不相同的比较,而这个正式‘与’的本质特征。

   走到这一步完了吗?当然还没有,不过已经接近重点了。那就是Shift-And的第2步?加1是为了什么?

   其实这个没有什么神秘之处,只是如果你对kmp不是特别熟,即便是很熟悉也有可能会忘记。就是在这幅图中

 

    我们幸运的是第4步发现了相同的c,但是如果没有发现呢?例如目标串的第26个字符不是c而是a呢?我们就会有第5步,和它比较的是谁呢?是第1个字符。这个意思是第4步失败,将要寻找c前面即a的最大前缀再加1的位置(和前3次一样)而我们默认a的最大前缀+1等于0+1=1.也就是很多其他博客中引用原作者说的那句话:空字符串也是目标串的后缀。a的前缀还有一个空字符。实际上本例也能看出来,第目标串第26个字符是a,显然有和模式串第一个字符a比较的需要。

 

       现在如果看懂了整个过程,可以去分析第一步和第二步所说是如此经典。

       不得不说,Shift-And算法是看透了KMP基于前缀匹配的本质特征,即比较的时候实际上是非黑即白的比较,使用01这种方法实在令人佩服。这个算法效率一般是KMP2倍以上。当然,基于位并行操作实际和机器字长有关系,比如32位限制或者其他,但是它在绝大部分机器上都能运行,除非机器字长为8(这种机器应该年龄很大了吧..),你所查询的是大于8位。

       至于Shift-Or,它所用的原理是一样的,只不过更加富有技巧性,使用了反码和取反等操作,加速D’的计算。有兴趣可以自行研究。如果看懂本例,在用点心相信看懂Shift-Or没什么问题。

        感谢Shift-And算法带我们走了一段神奇之旅!!!Wonderful!!

  

  • 大小: 7.4 KB
5
1
分享到:
评论
6 楼 十三月的 2013-04-28  
lijsf 写道
很好,第一次看到这个精妙的算法,学习了。ps:你的博客能订阅吗?

这个算法确实挺漂亮的,而且这种方法不止这一个。iteye有订阅功能没用过不太熟悉.
5 楼 lijsf 2013-04-28  
很好,第一次看到这个精妙的算法,学习了。ps:你的博客能订阅吗?
4 楼 十三月的 2013-04-12  
hbbbs 写道
   太深奥了。。。

期待做个视频连载,口语化一步步分析各种算法的精妙之处!

谢谢你的建议和鼓励,单纯的看这些博客确实特别需要耐心,等分析的多了自己也希望能做一个
3 楼 hbbbs 2013-04-12  
   太深奥了。。。

期待做个视频连载,口语化一步步分析各种算法的精妙之处!
2 楼 十三月的 2013-04-11  
javafound 写道
继续,可以出本书~

起个名字?
1 楼 javafound 2013-04-11  
继续,可以出本书~

相关推荐

    神经网络与量子计算的交叉研究.pptx

    神经网络与量子计算的交叉研究.pptx

    非线性端口 MEMS 麦克风的 Simscape 模型.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    用于超声成像和仿真的 MATLAB 工具箱.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    HFI高频注入仿真—matlab.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    北京工商大学上网登陆版源码.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    攻击离开优化器 (ALO)matlab代码.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    Ruby基于Ruby的MKS rebase脚本 Ruby语言基础

    【Ruby】基于Ruby的MKS rebase脚本 Ruby语言基础 将MKS网盘中其他工程路径下的工程文件批量rebase到目标工程路径。 【Ruby】基于Ruby的MKS rebase脚本 Ruby语言基础

    18.CSGO赛事管理系统的设计与实现-Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档

    18.CSGO赛事管理系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码(含数据库脚本)+开发文档+lw(高分毕设项目) 详细介绍链接:http://t.csdnimg.cn/CDBjW 内容概要: 全套项目源码+详尽文档,一站式解决您的学习与项目需求。 适用人群: 计算机、通信、人工智能、自动化等专业的学生、老师及从业者。 使用场景及目标: 无论是毕设、期末大作业还是课程设计,一键下载,轻松部署,助您轻松完成项目。 项目代码经过调试测试,确保直接运行,节省您的时间和精力。 其他说明: 项目整体具有较高的学习借鉴价值,基础能力强的可以在此基础上修改调整,以实现不同的功能。

    46.书籍学习平台的设计与实现-Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)论坛

    46.书籍学习平台的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)论坛,公告,付费专区,免费专区,销售,会员办理,书籍分类 详细设计文档链接:http://t.csdnimg.cn/GSeDN 内容概要: 全套项目源码+详尽文档,一站式解决您的学习与项目需求。 适用人群: 计算机、通信、人工智能、自动化等专业的学生、老师及从业者。 使用场景及目标: 无论是毕设、期末大作业还是课程设计,一键下载,轻松部署,助您轻松完成项目。 项目代码经过调试测试,确保直接运行,节省您的时间和精力。 其他说明: 项目整体具有较高的学习借鉴价值,基础能力强的可以在此基础上修改调整,以实现不同的功能。

    基于OpenCV+Tensorflow的银行卡号识别源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 基于OpenCVTensorflow的银行卡号识别源码+使用文档+全部资料(优秀项目).zip基于OpenCVTensorflow的银行卡号识别源码+使用文档+全部资料(优秀项目).zip基于OpenCVTensorflow的银行卡号识别源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    AI快速生成原创音乐的平台.txt

    AI快速生成原创音乐的平台.txt

    决斗者算法是一种元启发式优化算法matlab代码.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    xiuno模板知乎蓝魔改版源码附多个插件.zip

    xiuno模板知乎蓝魔改版源码附多个插件

    学习 C语言 编程语言 中的实敲代码仓库,提升自我的编程思维,编程能力 坚持下去.zip

    C语言诞生于美国的贝尔实验室,由丹尼斯·里奇(Dennis MacAlistair Ritchie)以肯尼斯·蓝·汤普森(Kenneth Lane Thompson)设计的B语言为基础发展而来,在它的主体设计完成后,汤普森和里奇用它完全重写了UNIX,且随着UNIX的发展,c语言也得到了不断的完善。为了利于C语言的全面推广,许多专家学者和硬件厂商联合组成了C语言标准委员会,并在之后的1989年,诞生了第一个完备的C标准,简称“C89”,也就是“ANSI C”,截至2020年,最新的C语言标准为2018年6月发布的“C18”。 [5] C语言之所以命名为C,是因为C语言源自Ken Thompson发明的B语言,而B语言则源自BCPL语言。 1967年,剑桥大学的Martin Richards对CPL语言进行了简化,于是产生了BCPL(Basic Combined Programming Language)语言。

    FS-S01059_STEP_01A.zip

    FS-S01059_STEP_01A.zip

    监听自身被卸载.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    基于遗传算法的公交排班系统分析matlab代码.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    基于深度强化学习的住宅区电动汽车充电策略

    基于深度强化学习的住宅区电动汽车充电策略是一种用于优化住宅区电动汽车充电行为的算法。面对日益增长的电动汽车数量和有限的充电资源,该算法结合了深度学习和强化学习方法,旨在实现住宅区电动汽车充电的智能调度和管理。

    第5章 s7200编程语言及指令系统.ppt

    第5章 s7200编程语言及指令系统.ppt

    基于遗传算法将电子卡车和电子三轮车路由到街道街区的客户matlab代码.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

Global site tag (gtag.js) - Google Analytics