数据结构 Sunday算法
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表示模板串):
- public class Sunday {
- // 数组容量可变,依字符范围而定
- private static final int MAX_SIZE = 65536;
- // 匹配失败时的移动距离
- private static final int[] MOVE_LENGTH = new int[MAX_SIZE];
- // 设置移动距离
- private static void setMoveLength(int tLen, String t) {
- int tLenPlusOne = tLen + 1;
- // 默认子串中的任何字符不出现在母串中,移动距离是子串长度 + 1
- for (int i = 0; i < MAX_SIZE; i++) {
- MOVE_LENGTH[i] = tLenPlusOne;
- }
- // 确定母串匹配部分最后一个字符的下一个字符在子串中最右出现的位置
- for (int i = 0; i < tLen; i++) {
- MOVE_LENGTH[t.charAt(i)] = tLen - i;
- }
- }
- // 顺序查找指定子串在指定母串中首次出现的位置
- public static int indexOf(String s, String t) {
- // 如果两个字符串至少有一个是null
- if (s == null || t== null) {
- return -1;
- }
- // 获取字符串长度
- int sLen = s.length();
- int tLen = t.length();
- // 设置移动距离
- setMoveLength(tLen, t);
- // i是母串遍历下标
- for (int i = 0; i < sLen; ) {
- // j是子串遍历下标
- int j = 0;
- // 不断匹配字符
- while (j < tLen && i + j < sLen && s.charAt(i + j) == t.charAt(j)) {
- j++;
- }
- // 如果查找成功
- if (j == tLen) {
- return i;
- }
- // 向右移动距离最小是1,i + tLen是匹配时最后一个字符下标
- // 如果该下标越界,则查找失败
- if (i + tLen >= sLen) {
- return -1;
- }
- // 右移对齐
- i += MOVE_LENGTH[s.charAt(i + tLen)];
- }
- // 查找失败
- return -1;
- }
- public static void main(String[] args) {
- String s = "searchsubstring";
- String t = "substring";
- System.out.println(indexOf(s, t));
- }
- }
结果:
- 6
参考资料
数据结构 Sunday算法的更多相关文章
- 字符串模式匹配sunday算法
文字部分转自:http://www.cnblogs.com/mr-ghostaqi/p/4285868.html 代码是我自己写的 今天在做LeetCode的时候,碰到一个写字符串匹配的题目: htt ...
- Sunday算法解决字符串匹配问题
概述 提起字符串匹配可能更多人会想到KMP算法,该算法时间复杂度为O(m+n),而且也是我们在学习数据结构过程中最早接触到的比较好的算法.但KMP算法需要在模式字符串有关联的情况下,也即模式字符串前后 ...
- 开启基本数据结构和算法之路--初识Graphviz
在我的Linux刀耕开荒阶段,就想开始重拾C,利用C实现常用的基本数据结构和算法,而数据结构和算法的掌握的熟练程度正是程序的初学者与职业程序员的分水岭. 那么怎么开启这一段历程呢? 按照软件工程的思想 ...
- 【转】MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- [转]MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
- MySQL索引背后的数据结构及算法原理【转】
本文来自:张洋的MySQL索引背后的数据结构及算法原理 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 ...
- 数据结构与算法JavaScript (一) 栈
序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...
- 数据结构与算法 Big O 备忘录与现实
不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新. 算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...
- 《java数据结构和算法》读书笔记
大学时并不是读计算机专业的, 之前并没有看过数据结构和算法,这是我第一次看. 从数据结构方面来说: 数组:最简单,遍历.查找很快:但是大小固定,不利于扩展 ...
随机推荐
- JavaMail在Windows平台下正常发送邮件,部署到Linux后则发送失败
问题: 在本机(Windows)环境下可以成功发送邮件,但部署到Linux服务器上后不能成功发送,前台不提示错误或提示502. linux下日志提示:javamail isssl false.... ...
- Web的几种上传方式总结
问题 文件上传在WEB开发中应用很广泛. 文件上传是指将本地图片.视频.音频等文件上传到服务器上,可以供其他用户浏览或下载的过程. 以下总结了常见的文件(图片)上传的方式和要点处理. 表单上传 这是传 ...
- SqlBulkCopy批量插入数据神器
1.简单例子 class Program { static void Main(string[] args) { Stopwatch sw = new Stopwatch(); DataTable d ...
- 【AtCoder】Tenka1 Programmer Contest 2019
Tenka1 Programmer Contest 2019 C - Stones 题面大意:有一个01序列,改变一个位置上的值花费1,问变成没有0在1右边的序列花费最少多少 直接枚举前i个都变成0即 ...
- net core体系-web应用程序-4net core2.0大白话带你入门-9asp.net core服务的生命周期
asp.net core服务的生命周期 Transient:每一次GetService都会创建一个新的实例 Scoped:在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request ...
- Codeforces 765F Souvenirs 线段树 + 主席树 (看题解)
Souvenirs 我们将询问离线, 我们从左往右加元素, 如果当前的位置为 i ,用一棵线段树保存区间[x, i]的答案, 每次更新完, 遍历R位于 i 的询问更新答案. 我们先考虑最暴力的做法, ...
- Java中常见的排序方式-冒泡排序(升序)
[基本思想] 假设数组为int[] a = { 49, 38, 65, 97, 76, 13, 27 },数组元素个数为7个. 第1轮比较:先是a[0]与a[1]比较,大于则先交换,再比较a[1]和a ...
- XXX系统项目目标文档课堂讨论
XXXX重大技术征集系统 1.讨论结果: 2.项目目标文档 A目标: 1. 实现普通用户在线需求填报,个人信息管理,需求结果查看. 2. 实现审核员用户的需求审核,需求查看浏览和生成图表结果. 3. ...
- Spring(三)实例化Bean以及注入对象
使用xml实例化bean 在xml中实例化bean的三种方式 <bean id="springService" class="com.zhiyou100.crm.t ...
- SQL语句中单引号、双引号和反引号的区分
反引号 反引号:反引号一般在Esc键的下方,为了区分MySQL的保留字与普通字符而引入的符号. 一般我们建表时都会将表名,库名都加上反引号来保证语句的执行度. 例如: SELECT * FROM `u ...