字符串匹配--Sunday算法
前面一篇博客详细介绍了KMP算法,KMP算法的代码不算繁琐,但是理解起来相对比较困难。
后来Daniel M.Sunday在1990年提出了Sunday算法,其思想是从前往后匹配,在匹配失败时关注的不是失配位而是主串中参加匹配的最末位字符的下一位字符
。
- 如果该字符没有在模式串中出现则在下一轮比较时直接跳过,即移动位置 = 模式串长度+ 1
- 如果该字符在模式串中出现过,假设其出现在模式串中的最右位置为P[j], 那么移动位置 = m (模式串长度) - j 。
举个例子说明下Sunday算法
1)第一轮比较,S[2]!=P[2],发生失配,那么就关注主串中参与匹配的最末位字符的下一位,也就是S[3] (图中绿色块),因为e不存在于模式串P中,那么就将模式串移动4位(pLen+1)
因为移动不大于pLen位的时候,在匹配时都需要将S[3]与模式串某个字符进行匹配,肯定是无法匹配上的,毕竟S[3]不存在于模式串P中
2)第二轮比较,同样的,S[6]!=P[2]发生失配,关注的字符就是S[7] “b”,它存在于模式串P中,移动模式串使得S[7]与该字符在模式串中最右的位置匹配上,即移动2位
3)第三轮就匹配上了
Sunday的思想比较简单,就直接上代码了
在Sunday算法中,我们关注主串中参与匹配的最末位字符的下一位(假设为X)是否存在于模式串中,根据其不同的结果移动的位数也不一样, 想要算法效率高,那么我们就需要快速地得到某个字符X是否存在于模式串中,以及对应需要位移的长度。
所以X是否存在于P不适合通过contains这样的函数来判断,因为其底层是通过逐步比较的方式,时间复杂度为O(m),效率很差,那么有什么更好的办法呢?
根据字符判断其是否存在于一个字符串中(字符集合), 我们可以想到map,不过其效率也不是很好。考虑到字符都可以用ASCII码来表示,那么我们就可以用一个数组来表示当X为不同字符时对应的位移长度
/*** 计算位移数组*/public static int[] calShiftArray(String p, int pLen) {int maxNum = 128;//使用ASCII码总个数作为位移数组的长度int[] shift = new int[maxNum];for (int i = 0; i < maxNum ; i++) {shift[i] = pLen + 1;}//对于模式串中存在的字符,其位移长度=模式串长度-其在模式串中出现的最右位置下标//因为shift计算的时候是i是从小到大,如果遇到两个相同的字符,那么较右侧的位移长度会覆盖前面的for (int i = 0; i < pLen; i++) {shift[p.charAt(i)] = pLen - i;}return shift;}
/*** sunday算法匹配* */public static int sundayAlogrithm( String s, String p) {int sLen = s.length();int pLen = p.length();int[] shift = calShiftArray(p, pLen);int i = 0;//表示与模式串第一位匹配的主串字符下标int j = 0;//表示模式串正在匹配的下标while (i <= sLen - pLen) {j = 0;while (Objects.equals(s.charAt(i+j), p.charAt(j))) {j++;if (j == pLen) {return i;}}//如果遇到P[j]!=S[i+j],说明发生失配,那么就移动模式串,移动长度=shift[x],x为关注的字符下标i = i + shift[s.charAt(i + pLen)];}return -1;}
Sunday算法的时间复杂度
从上面的分析来看,Sunday算法大大加速了失配时的位移速度,但是在最坏的情形下,其时间复杂度会变为O(m*n)
假设主串是aaabaaabaaabaaab,模式串是aaaa,我们可以知道aaaa不是上述主串的子串;在使用Sunday算法进行匹配的时候, 大部分情形下,关注字符都是在模式串中存在的(模式串只有a一个字符), 也就是说在大部分情形下模式串都只能移动1位,效率一下子降低了
那么最优的情形的,就是每次失配都可以移动 模式串长度+1 位,那么其时间复杂度就是O(n/m)
简单来说,Sunday最差情况的时间复杂度为O(m*n), 最优情况的时间复杂度为O(n/m)
参考:
从头到尾彻底理解KMP(2014年8月22日版)扩展2:Sunday算法
字符串匹配--Sunday算法相关推荐
- 字符串匹配——Sunday算法
字符串匹配--Sunday算法 基本思想及举例 Sunday算法由Daniel M.Sunday在1990年提出,它的思想跟BM算法很相似:1 只不过Sunday算法是从前往后匹配,在匹配失败时关注的 ...
- 字符串匹配--Sunday算法 1
字符串匹配(查找)算法是一类重要的字符串算法(String Algorithm).有两个字符串, 长度为m的haystack(查找串)和长度为n的needle(模式串), 它们构造自同一个有限的字母表 ...
- 字符串匹配 sunday算法
#include"iostream" #include"string.h" using namespace std;//BF算法 int strfind(cha ...
- kmp算法详解php,php中字符串匹配KMP算法实现例子
KMP算法是一个比较高级的算法了,加了改进了,下面我们来在php中实现KMP算法,希望例子对各位同学会带来帮助哦. kmp算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J. ...
- 字符串匹配——BMH算法
字符串匹配--BMH算法 给定主串T和模式串P,返回P在T中首次出现的位置,如果P不存在于T中,返回-1. 这样的问题就是字符串匹配问题,这里给出BMH算法的思想. 设主串T的长度为n,模式串P的长度 ...
- 字符串匹配——RabinKarp算法
字符串匹配--RabinKarp算法 给定主串T和模式串P,返回P在T中首次出现的位置,如果P不存在于T中,返回-1. 这样的问题就是字符串匹配问题,这里给出RabinKarp算法的思想. 设主串T的 ...
- 【超详细图解】字符串匹配Boyer-Moore算法:文本编辑器中的查找功能是如何实现的?
关于字符串匹配算法有很多,之前我有讲过一篇 KMP 匹配算法:图解字符串匹配 KMP 算法,不懂 kmp 的建议看下,写的还不错,这个算法虽然很牛逼,但在实际中用的并不是特别多.至于选择哪一种字符串匹 ...
- 两个字符串匹配度算法
在工作过程中,需要用到两个字符串匹配度算法,网上参考一些资料,写了一个匹配度算法类,项目中用到了而且效果很不错,今天给大家分享. 可以直接复制到你的项目中,就一个调用函数,非常简单. public c ...
- C++实现字符串匹配KMP算法
文章目录 1. 概述 2. 代码实现 3. 代码测试 1. 概述 Kmp算法的介绍及思想参阅下面两篇文章: 字符串匹配KMP算法 算法)通俗易懂的字符串匹配KMP算法及求next值算法 2. 代码实现 ...
最新文章
- svn idea使用
- 【PHP】 php7.0 扩展列表
- 小白入门学会将Eclipse中项目提交到github
- python——函数 10、函数的嵌套
- logistic 回归_具有Logistic回归的优秀初学者项目
- 经典面试题(41):以下代码将输出的结果是什么?
- HttpServletRequest说明
- 7.1.21 jQuery 的 Post请求
- [py]py常用模块小结
- 严蔚敏数据结构之线性表的基本操作
- 蚂蚁课堂学习笔记之springAop和Ioc
- 独立游戏人:像素风格游戏制作分享(转)
- 计算机派位志愿填报技巧,小升初电脑大派位:大派位操作流程及志愿填报
- 计算机运行很卡很慢,电脑运行慢很卡怎么办 电脑运行卡的解决方法
- 关于spring data jpa 仓储层自动实现
- 华为、苹果,为何“盯”上二手机?
- 【文献翻译】自动实施与Windows相关的安全配置指南
- 外贸管理软件CRM、ERP对外贸企业有什么用?
- 深信服超融合基础架构管理平台--虚拟网络测试实践
- 做为一名大数据新手,应该通过这篇文章了解大数据
热门文章
- RocketMQ API使用简介、拉取机制
- php use include区别,php use和include区别总结
- sqlconfigdatasource mysql_MFC odbc 连接MySQL 的 (SQLConfigDataSource动态DSN)
- Lindström–Gessel–Viennot lemma
- MySQL拷贝表的几种方式
- tcp_handle_req: Made 4 read attempts but message is not complete yet - closing connection
- Java 8 集合不完全一览
- YY提交招股书赴美上市:连续三季盈利(转)
- IBOOKS导入EPUB出现-23错误时解决方法
- HDU - 4821 String(字符串哈希+优化)