简单高效的字符串匹配算法

article/2025/9/21 12:30:03

Quick Search算法

算法简介

Quick Search算法属于Sunday算法的一种。Sunday算法由Daniel M Sunday在1990年提出。论文原文:A VERV FAST SU6STRINC SEARCH ALGORITHM

在论文中,作者提出了三个不同的算法:Quick Search算法、Maximal Shift算法以及Optimal Mismatch算法。作者证明了这三种算法效率均优于Boyer-Moore算法。其中,Optimal Mismatch略微好于前两者。但在原理及应用上,Quick Search最为简单。

Quick Search可以被视为一种简化的Boyer-Moore算法。该算法仅使用Boyer-Moore中的“坏字符”规则。此外,与Boyer-Moore算法不同,Quick Search在匹配字符串时是按从头到尾的顺序匹配的。

在下面的描述中,字符串s为目标串(主串、被匹配串),长度为n;字符串p被称为模式串(子串、匹配串),长度为m。

算法步骤

首先将字符串s与p头部对齐,开始以下步骤:

  1. 从p的头部至尾部开始逐一与s匹配

  2. 若匹配成功返回对应位置。若匹配失败,则聚焦到s与p匹配范围外的第一个字符c(图中绿色框)。

  3. 向右移动p,令p中最后一个c与s中的c对齐,如果p中不存在c,则将整个p向后移动m+1位。回到步骤1,重复步骤1、2、3。

请添加图片描述

以上匹配操作的时间复杂度为 O ( n ) O(n) O(n)。为了对任意一个字符c,我们都能快速定位到其在p中最后出现的位置,在执行以上匹配之前需要进行预处理:

基于字符串p构造一个数组a,数组长度等于字符串中所有可能出现的字符数(一般为256),字符对应的数组元素为该字符在p中最后出现的位置与字符串末端的距离+1,举个例子,字符串p为“abc”,则a[‘a’] = 3, a[‘b’] = 2, a[‘c’] = 1。其他未出现的字符对应的数组元素则统一赋值为p的长度+1。预处理操作的时间复杂度为 O ( m ) O(m) O(m)

在匹配过程中,对于s中的任意一个字符c,通过a[c]即可得到p向后移动的位数。

代码

#define ALLCHAR 256int QuickSearch(char* s, char *p) {int n = strlen(s), m = strlen(p);int a[ALLCHAR];for (int i=0; i<ALLCHAR; ++i)   //初始化数组aa[i] = m + 1;for (int i=0; i<m; ++i)         //预处理a[p[i]] = m - i; int now = 0;while (now <= n - m) {if (memcmp(p, s + now, m) == 0)return now;now += a[s[now + m]];            }return -1;
}



Horspool算法

算法简介

Horspool同样是简化版的Boyer-Moore算法。该算法仅使用“坏字符”规则,字符串匹配时与Boyer-Moore算法一样,按从尾到头的顺序。

算法步骤

首先将字符串s与p头部对齐,开始以下步骤:

  1. 从p的尾部至头部开始逐一与s匹配

  2. 若匹配成功返回对应位置。若匹配失败,则聚焦到s与p匹配范围内的最后一个字符c(图中绿色框)。
    请添加图片描述

  3. 向右移动p,令p中除最后一位外最后出现的c与s中的c对齐,如果p中不存在c,则将整个p向后移动m位。回到步骤1,重复步骤1、2、3。

同理,在执行以上匹配操作前需要预处理:基于字符串p构造一个数组a,数组长度等于字符串中所有可能出现的字符数(一般为256),字符对应的数组元素为该字符在p中除最后一位外,最后出现的位置与字符串末端的距离,举个例子,字符串p为“abc”,则a[‘a’] = 2, a[‘b’] = 1, a[‘c’] = m = 3。其他未出现的字符对应的数组元素则统一赋值为p的长度。

代码

#define ALLCHAR 256int Horspool(char *s, char *p) {int n = strlen(s), m = strlen(p);int a[ALLCHAR];for (int i=0; i<ALLCHAR; ++i)a[i] = m;for (int i=0; i<m-1; ++i)a[p[i]] = m-i-1;int now = 0;while (now <= n-m) {if (p[m-1]==s[now+m-1] && memcmp(p, s+now, m-1)==0)return now;now += a[s[now+m-1]];}return -1;
}



参考资料

EXACT STRING MATCHING ALGORITHMS

Quick Search algorithm

A VERV FAST SU6STRINC SEARCH ALGORITHM

Horspool algorithm


http://chatgpt.dhexx.cn/article/UFEy1ZLK.shtml

相关文章

算法之字符串匹配

字符串匹配&#xff1a;设 S 和 T 是给定的两个串&#xff0c;在主串 S 中找到模式串 T 的过程称为字符串匹配&#xff0c;如果在主串 S 中找到模式串 T &#xff0c;则称匹配成功&#xff0c;函数返回 T 在 S 中首次出现的位置&#xff0c;否则匹配不成功&#xff0c;返回 -1。…

经典字符串匹配算法——KMP算法

KMP算法 KMP算法是一种高效的字符串匹配算法&#xff0c;在传统暴力遍历匹配的基础上做了一定的优化。 首先KMP算法的实现也是使用了回退思想&#xff0c;不过与暴力遍历不同&#xff0c;KMP的回退&#xff0c;是让子串进行匹配&#xff0c;而不是主串。 KMP示例 首先我们来…

16.算法之字符串匹配算法

前言 字符串匹配是我们在程序开发中经常遇见的功能&#xff0c;比如sql语句中的like,java中的indexof,都是用来判断一个字符串是否包含另外一个字符串的。那么&#xff0c;这些关键字&#xff0c;方法&#xff0c;底层算法是怎么实现的么&#xff1f;本节&#xff0c;我们来探…

字符串匹配算法(BM)

文章目录 1. BM&#xff08;Boyer-Moore&#xff09;算法1.1 坏字符规则1.2 好后缀规则1.3 两种规则如何选择 2. BM算法代码实现2.1 坏字符2.2 好后缀2.3 完整代码2.4 调试 3. 总结 1. BM&#xff08;Boyer-Moore&#xff09;算法 思想&#xff1a;有模式串中不存在的字符&…

六种字符串匹配算法详解(含代码演示)

1. Brute-Force算法 2. Rabin-Karp Hash算法 3. Kmp算法 4. Kmp的优化算法 5. Sunday算法 6. Shift-And算法 ps&#xff1a;字符串匹配其实是单模匹配问题 1.Brute-Force 朴素匹配算法&#xff08;暴力匹配&#xff09; 时间复杂度&#xff1a;O(n*m) //返回 文本串s中第一…

字符串匹配算法(BF、KMP)

BF算法 描述&#xff1a; BF&#xff0c;Brute Force&#xff0c;暴力匹配的意思&#xff0c;是最简单直观的字符串匹配算法。假设有主串s1和子串s2&#xff0c;根据BF算法判断s1是否包含s2的步骤如下&#xff1a; 初始下标指针 i, j 分别指向s1, s2的首位置&#xff0c;若s1…

这可能是全网最好的字符串匹配算法讲解

点击上方 好好学java &#xff0c;选择 星标 公众号重磅资讯&#xff0c;干货&#xff0c;第一时间送达 今日推荐&#xff1a;14 个 github 项目&#xff01;个人原创100W 访问量博客&#xff1a;点击前往&#xff0c;查看更多为保证代码严谨性&#xff0c;文中所有代码均在 le…

Spring boot 项目(五)——AOP切面

一、AOP简介 1、在软件业&#xff0c;AOP为Aspect Oriented Programming的缩写&#xff0c;意为&#xff1a;面向切面编程&#xff0c;通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。 2、AOP是OOP的延续&#xff0c;是软件开发中的一个热点&#xff0c;也…

Spring AOP 切面(Aspect)应用详解

1. AOP 切面应用 下面是一个AOP切面的一个简单的应用实例 引入AOP依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>创建切面类对象 Aspect Component pub…

springboot实现AOP切面编程

概述 AOP(Aspect Oriented Programming) 即面向切面编程。面向切面是面向对象中的一种方式而已。在代码执行过程中&#xff0c;动态嵌入其他代码&#xff0c;叫做面向切面编程&#xff08;将交叉业务逻辑封装成成切面&#xff0c;利用AOP功能将切面织入到主业务逻辑———与主…

spring AOP切面及日志记录实现

目录 1.什么是AOP切面 2.理解AOP 3.AOP实例 1.自定义注解 2.创建一个切面类 3.将自定义注解标注在测试接口上 1.什么是AOP切面 AOP&#xff08;Aspect Oriented Programming&#xff09;&#xff0c;面向切面思想&#xff0c;是Spring的三大核心思想之一。 在项目中经常…

Aop切面自定义注解的使用

一&#xff1a;功能简介 本文主要记录如何使用aop切面的方式来实现日志记录功能。 主要记录的信息有: 操作人&#xff0c;方法名&#xff0c;参数&#xff0c;运行时间&#xff0c;操作类型(增删改查)&#xff0c;详细描述&#xff0c;返回值。 二&#xff1a;项目结构图 三…

AOP切面注解

一.前言 在以前的项目中&#xff0c;很少去关注spring aop的具体实现与理论&#xff0c;只是简单了解了一下什么是aop具体怎么用&#xff0c;看到了一篇博文写得还不错&#xff0c;就转载来学习一下&#xff0c;博文地址&#xff1a;http://www.cnblogs.com/xrq730/p/4919025.h…

AOP切面执行顺序

文章目录 一. 概述二. 讲述1. 单切面中各通知方法的执行顺序2. 多切面中各通知方法的执行顺序3. 多切面的通知方法中抛出异常 参考资料 一. 概述 本文主要讲述以下几点 单AOP切面时&#xff0c;各通知方法的执行顺序。多AOP切面时&#xff0c;多切面的执行顺序和各通知方法的执…

spring aop切面执行顺序

spring aop切面执行顺序 切面执行顺序 现有切面1、切面2对同一个切点按先后顺序执行&#xff08;切面1先于切面2执行&#xff09; 切面1&#xff1a;Before、After、AfterReturnning、AfterThrowing、Around 执行前、Around 正常执行、Around 异常执行、Around 执行后切面2&am…

一文带你搞定AOP切面

摘要&#xff1a;AOP在spring中又叫“面向切面编程”&#xff0c;是对传统我们面向对象编程的一个补充&#xff0c;主要操作对象就是“ 切面”&#xff0c; 可以简单的理解它是贯穿于方法之中&#xff0c;在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。 本文分…

SpringBoot AOP切面实现

文章目录 一、AOP简介二、AOP体系与概念三、AOP实例1、创建SpringBoot工程2、添加依赖3、AOP相关注解3.1、Aspect3.2、Pointcut3.2.1、execution()3.2.2、annotation() 3.3、Around3.4、Before3.5、After3.6、AfterReturning3.7、AfterThrowing 一、AOP简介 AOP&#xff08;As…

AOP切面编程的理解

一、什么是Spring的AOP&#xff1f; AOP在spring中又叫“面向切面编程”&#xff0c;它可以说是对传统我们面向对象编程的一个补充&#xff0c;从字面上顾名思义就可以知道&#xff0c;它的主要操作对象就是“切面”&#xff0c;所以我们就可以简单的理解它是贯穿于方法之中&a…

AOP切面使用

一、主要设计注解&#xff1a; Aspect After before Pointcut Around pom文件引入 <!--用于aop切面编程--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> 二、AOP核心…

AOP面向切面

1.什么是Spring的AOP? AOP又叫"面向切面编程",是对传统的面向对象编程的一个补充,主要的操作对象就是"切面 ",可以简单的理解它是贯穿于方法之中,在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。 相当于将我们原本一条线执行的程序在中间切…