字符串匹配查找算法中,最着名的两个是KMP算法(Knuth-Morris-Pratt)和BM算法(Boyer-Moore)。两个算法在最坏情况下均具有线性的查找时间。但是在实用上,KMP算法并不比最简单的C库函数strstr()快多少,而BM算法则往往比KMP算法快上3-5倍(未亲身实践)。但是BM算法还不是最快的算法,这里介绍一种比BM算法更快一些的查找算法Sunday算法。
 
   Sunday算法的思想和BM算法中的坏字符思想非常类似。差别只是在于Sunday算法在匹配失败之后,是取目标串中当前和Pattern字符串对应的部分后面一个位置的字符来做坏字符匹配。
 
   当发现匹配失败的时候就判断母串中当前偏移量+Pattern字符串长度+1处(假设为K位置)的字符在Pattern字符串中是否存在。如果存在,则将该位置和Pattern字符串中的该字符对齐,再从头开始匹配;如果不存在,就将Pattern字符串向后移动,和母串k+1处的字符对齐,再进行匹配。重复上面的操作直到找到,或母串被找完结束托福答案 www.yztrans.com
 
   动手写了个小例子来实现以下这个算法。
 
   在代码中,实现了两种字符串匹配算法,一种是Sunday方式,一种是普通的每次移动一位的方式,二者的效率对比在main函数中有,都是纳秒级别。算法的详细步骤,在代码中已经添加了相应的注释。关于BM算法,下次空了再一起对照着分析 www.lefeng123.com
 
   1 import java.util.HashMap;
 
   2 import java.util.LinkedList;
 
   3 import java.util.List;
 
   4 import java.util.Map;
 
   5
 
   6 /**
 
   7 * @author Scott
 
   8 * @date 2013年12月28日
 
   9 * @description
 
   10 */
 
   11 public class SundySearch {
 
   12 String text = null;
 
   13 String pattern = null;
 
   14 int currentPos = 0;
 
   15
 
   16 /**
 
   17 * 匹配后的子串第一个字符位置列表
 
   18 */
 
   19 List<Integer> matchedPosList = new LinkedList<Integer>();
 
   20
 
   21 /**
 
   22 * 匹配字符的Map,记录改匹配字符串有哪些char并且每个char最后出现的位移
 
   23 */
 
   24 Map<Character, Integer> map = new HashMap<Character, Integer>();
 
   25
 
   26 public SundySearch(String text, String pattern) {
 
   27 this.text = text;
 
   28 this.pattern = pattern;
 
   29 this.initMap();
 
   30 };
 
   31
 
   32 /**
 
   33 * Sunday匹配时,用来存储Pattern中每个字符最后一次出现的位置,从左到右的顺序
 
   34 */
 
   35 private void initMap() {
 
   36 for (int i = 0; i < pattern.length(); i++) {
 
   37 this.map.put(pattern.charAt(i), i);
 
   38
 
   39 }
 
   40 }
 
   41
 
   42 /**
 
   43 * 普通的字符串递归匹配,匹配失败就前进一位
 
   44 */
 
   45 public List<Integer> normalMatch() {
 
   46 //匹配失败,继续往下走
 
   47 if (!matchFromSpecialPos(currentPos)) {
 
   48 currentPos += 1;
 
   49
 
   50 if ((text.length() - currentPos) < pattern.length()) {
 
   51 return matchedPosList;
 
   52 }
 
   53 normalMatch();
 
   54 } else {
 
   55 //匹配成功,记录位置
 
   56 matchedPosList.add(currentPos);
 
   57 currentPos += 1;
 
   58 normalMatch();
 
   59 }
 
   60
 
   61 return matchedPosList;
 
   62 }
 
   63
 
   64 /**
 
   65 * Sunday匹配,假定Text中的K字符的位置为:当前偏移量+Pattern字符串长度+1
 
   66 */
 
   67 public List<Integer> sundayMatch() {
 
   68 // 如果没有匹配成功
 
   69 if (!matchFromSpecialPos(currentPos)) {
 
   70 // 如果Text中K字符没有在Pattern字符串中出现,则跳过整个Pattern字符串长度
 
   71 if ((currentPos + pattern.length() + 1) < text.length()
 
   72 && !map.containsKey(text.charAt(currentPos + pattern.length() + 1))) {
 
   73 currentPos += pattern.length();
 
   74 }else {
 
   75 // 如果Text中K字符在Pattern字符串中出现,则将Text中K字符的位置和Pattern字符串中的最后一次出现K字符的位置对齐
 
   76 if ((currentPos + pattern.length() + 1) > text.length()) {
 
   77 currentPos += 1;
 
   78 } else {
 
   79 currentPos += pattern.length() - (Integer) map.get(text.charAt(currentPos + pattern.length()));
 
   80 }
 
   81 }
 
   82
 
   83 // 匹配完成,返回全部匹配成功的初始位移
 
   84 if ((text.length() - currentPos) < pattern.length()) {
 
   85 return matchedPosList;
 
   86 }
 
   87
 
   88 sundayMatch();
 
   89 }else {
 
   90 // 匹配成功前进一位然后再次匹配
 
   91 matchedPosList.add(currentPos);
 
   92 currentPos += 1;
 
   93 sundayMatch();
 
   94 }
 
   95 return matchedPosList;
 
   96 }
 
   97
 
   98 /**
 
   99 * 检查从Text的指定偏移量开始的子串是否和Pattern匹配
 
   100 */
 
   101 public boolean matchFromSpecialPos(int pos) {
 
   102 if ((text.length()-pos) < pattern.length()) {
 
   103 return false;
 
   104 }
 
   105
 
   106 for (int i = 0; i < pattern.length(); i++) {
 
   107 if (text.charAt(pos + i) == pattern.charAt(i)) {
 
   108 if (i == (pattern.length()-1)) {
 
   109 return true;
 
   110 }
 
   111 continue;
 
   112 } else {
 
   113 break;
 
   114 }
 
   115 }
 
   116
 
   117 return false;
 
   118 }
 
   119
 
   120 public static void main(String[] args) {
 
   121 SundySearch sundySearch = new SundySearch("hello 啊啊 阿道夫 adfsadfklf adf234masdfsdfdsfdsfdsffwerwrewrerwerwersdf2666sdflsdfk", "adf");
 
   122
 
   123 long begin = System.nanoTime();
 
   124 System.out.println("NormalMatch:" + sundySearch.normalMatch());
 
   125 System.out.println("NormalMatch:" + (System.nanoTime() - begin));
 
   126
 
   127 begin = System.nanoTime();
 
   128 System.out.println("SundayMatch:" + sundySearch.sundayMatch());
 
   129 System.out.println("SundayMatch:" + (System.nanoTime() - begin));
 
   130
 
   131 }
 
   132 }
 
   运行结果:
 
   NormalMatch:[13, 17, 24]
 
   NormalMatch:313423
 
   SundayMatch:[13, 17, 24]
 
   SundayMatch:36251

字符串匹配算法之Sunday算法的更多相关文章

  1. 字符串匹配算法之Sunday算法(转)

    字符串匹配算法之Sunday算法 背景 我们第一次接触字符串匹配,想到的肯定是直接用2个循环来遍历,这样代码虽然简单,但时间复杂度却是Ω(m*n),也就是达到了字符串匹配效率的下限.于是后来人经过研究 ...

  2. 字符串匹配算法:Sunday算法

    背景 我们第一次接触字符串匹配,想到的肯定是直接用2个循环来遍历,这样代码虽然简单,但时间复杂度却是\(Ω(m*n)\),也就是达到了字符串匹配效率的下限.于是后来人经过研究,构造出了著名的KMP算法 ...

  3. 动画演示Sunday字符串匹配算法——比KMP算法快七倍!极易理解!

    前言 上一篇我用动画的方式向大家详细说明了KMP算法(没看过的同学可以回去看看). 这次我依旧采用动画的方式向大家介绍另一个你用一次就会爱上的字符串匹配算法:Sunday算法,希望能收获你的点赞关注收 ...

  4. 字符串匹配算法之 kmp算法 (python版)

    字符串匹配算法之 kmp算法 (python版) 1.什么是KMP算法 KMP是三位大牛:D.E.Knuth.J.H.MorriT和V.R.Pratt同时发现的.其中第一位就是<计算机程序设计艺 ...

  5. 字符串匹配算法之BM算法

    BM算法,全称是Boyer-Moore算法,1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹配算法. BM算法定义了两个规则: ...

  6. Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化

    1. 字符串匹配算法 所谓字符串匹配算法,简单地说就是在一个目标字符串中查找是否存在另一个模式字符串.如在字符串 "ABCDEFG" 中查找是否存在 "EF" ...

  7. 字符串匹配算法之————KMP算法

    上一篇中讲到暴力法字符串匹配算法,但是暴力法明显存在这样一个问题:一次只移动一个字符.但实际上,针对不同的匹配情况,每次移动的间隔可以更大,没有必要每次只是移动一位: 关于KMP算法的描述,推荐一篇博 ...

  8. 字符串匹配算法之kmp算法

    kmp算法是一种效率非常高的字符串匹配算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,所以简称KMP算法 算法思想 在一个字符串中查找另一个字符串时,会遇到如下图的情况 我们通常 ...

  9. 字符串匹配算法(二)-BM算法详解

    我们在字符串匹配算法(一)学习了BF算法和RK算法,那有没更加高效的字符串匹配算法呢.我们今天就来聊一聊BM算法. BM算法 我们把模式串和主串的匹配过程,可以看做是固定主串,然后模式串不断在往后滑动 ...

随机推荐

  1. oracle触发器使用总结

    1.说明 1)触发器是一种特殊的存储过程,触发器一般由事件触发并且不能接受参数,存储器由语句块去调用 2)触发器分类: 1.DML触发器: 创建在表上,由DML事件引发 2.instead of触发器 ...

  2. delphi 自定义消息

    delphi 自定义消息     消息描述 Tmsg是   Windows系统用来记录描述一个具体的windows消息的.就是windows   用于封装应用程序及系统程序发生的消息,它是操作系统使用 ...

  3. Android 各版本信息 (维基百科)

    The following tables show the release dates and key features of all Android operating system updates ...

  4. C# 将数据集以excel的形式输出

    private void SaveLastMonthAuthorPays()        {            string fileName = "LastMonthAuthorPa ...

  5. 《算法问题实战策略》-chaper14-整数论

    Lucas定理: 在组合计数问题中,我们常面临组合数C(n,m)过大而无法直接计算的困境,那么这里的Lucas定理给出了一个较大组合数进行取余运算的一种递归算法. 什么是Lucas定理? Lucas定 ...

  6. openSource clouds

    学习当前较主流的开源云基础设施管理软件by Ruiy summarize publish; 我擦,有不时候Ruiy干事也就那吊风格,啥事也就那么随口一说,你们太sensitivity,同网络延迟对存储 ...

  7. [原创]python MySQLdb在windows环境下的安装、出错问题以及解决办法

    版权声明:本文为博主原创文章,未经博主允许不得转载. 问题:windows下安装MySQLdb的方法 解析:python没有php那种集成环境,比如wamp那种集成软件直接把所有需要的东西全部一次性搭 ...

  8. SheetOffice控件使用分享

    1.  控件属性及说明 Template:套用的模板目录(套用模板会使用到) 模板中必须包含书签: Body,这个是在代码中写死了的,是把当前文档的内容插入到模板的Body书签中. 如果使用印章,必须 ...

  9. 【深入了解cocos2d-x 3.x】定时器(scheduler)的使用和原理探究(3)

    上篇文章分析到了定时器的定义.这篇的重点就是定时器是怎样执行起来的. 1.从main中寻找定时器的回调 讲定时器的执行,就不得不触及到cocos2dx的main函数了,由于定时器是主线程上执行的.并非 ...

  10. HDFS集群balance(4)-- 测试计划

    转载请注明博客地址:http://blog.csdn.net/suileisl HDFS集群balance,对应版本balance design 6 如需word版本,请QQ522173163联系索要 ...