Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配算法。相对比较KMP和BM算法而言,简单了许多。

  Sunday算法的思想类似于BM算法中的坏字符思想,有点像其删减版。差别在于Sunday算法在失配之后,是取目标串中当前和模式串匹配的部分后面一个位置的字符来做坏字符匹配。其时间复杂度和BM算法差不多,平均性能的时间复杂度也为O(n)。Sunday算法的位移比BM算法更大,所以Sunday算法的效率比BM算法更高,在匹配随机字符串时效率比其他匹配算法快。最差情况的时间复杂度为O(n * m),考虑如下目标串:baaaabaaaabaaaabaaaa,在里面搜索aaaaa,没有匹配位置。如果用Sunday算法,坏字符大部分都是a,而模式串中又全部都是a,所以在大部分情况下,失配后模式串只能往右移动1位。

匹配原理:从前往后匹配,如果不匹配,则根据母串S对齐部分的最后一个字符的下一个字符进行判断:如果该字符出现在模板串T中,则选择最右出现的位置进行对齐;否则,直接跳过该匹配区域。

  母串S:s e a r c h s u b s t r i n g

  模板串T:s u b s t r i n g

  开始匹配(第1个字符):

  s e a r c h s u b s t r i n g

  s u b s t r  i n g

  继续下一字符匹配(第2个字符):

  s e a r c h s u b s t r i n g

  s u b s t r  i  n g

  出现不匹配情况,查找母串对齐部分的最后一个字符的下一个字符s。在T中,字符s出现两次,按照原理,选择最右位置出现的s进行对齐,那么可以得到:

  s e a r c h s u b s t r i n g

                   s u b s t r i n g

  假设母串S为:s e a r c h s u b z t r i n g

  那么当匹配到上述情况时,字符z在T中没有出现,那么就可以得到下面的情况:

  s e a r c h s u b z t r i n g

         s u b s t r i n g

  这就是其原理的两种情况。

  Java语言实现(s表示母串,t表示模板串):

  1. public class Sunday {
  2. // 数组容量可变,依字符范围而定
  3. private static final int MAX_SIZE = 65536;
  4. // 匹配失败时的移动距离
  5. private static final int[] MOVE_LENGTH = new int[MAX_SIZE];
  6.  
  7. // 设置移动距离
  8. private static void setMoveLength(int tLen, String t) {
  9. int tLenPlusOne = tLen + 1;
  10. // 默认子串中的任何字符不出现在母串中,移动距离是子串长度 + 1
  11. for (int i = 0; i < MAX_SIZE; i++) {
  12. MOVE_LENGTH[i] = tLenPlusOne;
  13. }
  14.  
  15. // 确定母串匹配部分最后一个字符的下一个字符在子串中最右出现的位置
  16. for (int i = 0; i < tLen; i++) {
  17. MOVE_LENGTH[t.charAt(i)] = tLen - i;
  18. }
  19. }
  20.  
  21. // 顺序查找指定子串在指定母串中首次出现的位置
  22. public static int indexOf(String s, String t) {
  23. // 如果两个字符串至少有一个是null
  24. if (s == null || t== null) {
  25. return -1;
  26. }
  27.  
  28. // 获取字符串长度
  29. int sLen = s.length();
  30. int tLen = t.length();
  31. // 设置移动距离
  32. setMoveLength(tLen, t);
  33.  
  34. // i是母串遍历下标
  35. for (int i = 0; i < sLen; ) {
  36. // j是子串遍历下标
  37. int j = 0;
  38. // 不断匹配字符
  39. while (j < tLen && i + j < sLen && s.charAt(i + j) == t.charAt(j)) {
  40. j++;
  41. }
  42.  
  43. // 如果查找成功
  44. if (j == tLen) {
  45. return i;
  46. }
  47.  
  48. // 向右移动距离最小是1,i + tLen是匹配时最后一个字符下标
  49. // 如果该下标越界,则查找失败
  50. if (i + tLen >= sLen) {
  51. return -1;
  52. }
  53.  
  54. // 右移对齐
  55. i += MOVE_LENGTH[s.charAt(i + tLen)];
  56. }
  57.  
  58. // 查找失败
  59. return -1;
  60. }
  61.  
  62. public static void main(String[] args) {
  63. String s = "searchsubstring";
  64. String t = "substring";
  65. System.out.println(indexOf(s, t));
  66. }
  67.  
  68. }

  结果:

  1. 6

  参考资料

  【模式匹配】之 —— Sunday算法

  数据结构与算法系列----Sunday算法详解

BF、KMP、BM、Sunday算法讲解

数据结构 Sunday算法的更多相关文章

  1. 字符串模式匹配sunday算法

    文字部分转自:http://www.cnblogs.com/mr-ghostaqi/p/4285868.html 代码是我自己写的 今天在做LeetCode的时候,碰到一个写字符串匹配的题目: htt ...

  2. Sunday算法解决字符串匹配问题

    概述 提起字符串匹配可能更多人会想到KMP算法,该算法时间复杂度为O(m+n),而且也是我们在学习数据结构过程中最早接触到的比较好的算法.但KMP算法需要在模式字符串有关联的情况下,也即模式字符串前后 ...

  3. 开启基本数据结构和算法之路--初识Graphviz

    在我的Linux刀耕开荒阶段,就想开始重拾C,利用C实现常用的基本数据结构和算法,而数据结构和算法的掌握的熟练程度正是程序的初学者与职业程序员的分水岭. 那么怎么开启这一段历程呢? 按照软件工程的思想 ...

  4. 【转】MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  5. [转]MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  6. MySQL索引背后的数据结构及算法原理【转】

    本文来自:张洋的MySQL索引背后的数据结构及算法原理 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 ...

  7. 数据结构与算法JavaScript (一) 栈

    序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...

  8. 数据结构与算法 Big O 备忘录与现实

    不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新.        算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...

  9. 《java数据结构和算法》读书笔记

    大学时并不是读计算机专业的, 之前并没有看过数据结构和算法,这是我第一次看.         从数据结构方面来说:                数组:最简单,遍历.查找很快:但是大小固定,不利于扩展 ...

随机推荐

  1. C# 操作windows服务[启动、停止、卸载、安装]

    主要宗旨:不已命令形式操作windows服务 static void Main(string[] args) { var path = @"E:\开发辅助项目\WCF\WCF.Test\WC ...

  2. WCF 配置App.Config

    <system.serviceModel> <bindings> <basicHttpBinding> <binding name="/> & ...

  3. linux dig 命令使用方法

    ref:https://www.imooc.com/article/26971?block_id=tuijian_wz dig 命令主要用来从 DNS 域名服务器查询主机地址信息. 查询单个域名的 D ...

  4. zookeeper都有哪些使用场景

    分布式协调 这个其实是zk很经典的一个用法,比如,A系统发送个请求到mq,然后B拿到消息消费之后处理了.那A系统如何知道B系统的处理结果? 用zk就可以实现分布式系统之间的协调工作.A系统发送请求之后 ...

  5. 解开一个疑惑,为什么LVS开放的端口,使用netstat或ss命令,不能查找到其监听的端口呢?

    RT, 这个疑问,本周一直在心里,今天找到一个说法. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 另外LVS规则算是内核方法,用netstat -ntulp也显 ...

  6. [转] mongoose 之Shema

    总 之见到我写点啥简直是奇迹,由于现在喜欢上玩转node.js +mongoose,个人爱好,靠近前端的又是英文文档,苦逼得很,悟出来一个写一个吧.之前喜欢误打误撞,网上搜索一点解决一下问题,后来实在 ...

  7. Python_collections_deque双向队列

    deque:创建一个双向队列 import collections collections.deque(['nihao','x']) x.append():在列表的右边添加 x.appendleft( ...

  8. Codeforces 342D Xenia and Dominoes 状压dp

    码就完事了. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define ...

  9. mysql实现简单的增删改查,放入xmapp自带数据库中

    1.mysql概念:SQL-Structured Query Language,是一种特殊的语言,专用于操作关系型数据库服务器中的数据,所有的SQL语句分为四类: (1)DDL(2)DQL(3)DML ...

  10. rc.local(ubuntu18.04)

    系统自带服务/lib/systemd/system/rc-local.service 软连接为 /lib/systemd/system/rc.local.service -> rc-local. ...