学习笔记——KMP

embedded/2024/11/14 3:17:21/

字符匹配算法一直是所有人的噩梦。除却难懂的思路,难卡的算法复杂度也是一个问题
下面是少许常见字符匹配算法及其常见衍生算法
在这里插入图片描述
也许有点看不清楚,但大致可以看到KMP算法的衍生算法是最多的

大致优缺点
KMP:速度平均O(n+m),最慢O(nm)
BM&Sunday(未写):速度平均O(n),最慢O(nm)
哈希(未写):平均复杂度O(n),但有冲突风险,基本万能
(仅罗列单字符串比较)
其中BM&Sunday都是KMP的优化,所以优先讲KMP

什么是KMP

KMP是一种单字符串比较问题
举个例子:
有文本串 S S S S S C SSSSSC SSSSSC和模式串 S S C SSC SSC
现在要在文本串中找出模式串,请问怎么办?
肉眼都可以知道SSC在哪里,但如果文本串太长,就不方便了

因此,暴力法应运而生,以效率低下但十分稳定而著称

方法:对于每个文本串中的字母作为开头,匹配模式串

代码:

const int N=1007//基本是最大值
int find(int s[],int t[],int n,int m){for(int i=0;i+m-1<n;i++){bool flg=1;for(int j=0,k=i;j<m;j++,k++)if(s[k]!=t[j])flg=0;if(flg)return i;}return -1;
}

有一种简洁而不失优雅的暴力美
怎么优化?
不难发现暴力法每一步都没有利用好上次的量,但怎么利用呢?
很容易发现,我们希望每次 j j j回退的距离尽量小
首先,我们希望能够最好是对于以一个节点为结尾(开头也可以,但结尾方便),迅速找到其对应的最远的长度。(说白了就是找出最大的 l e n len len,满足文本串 [ i − l e n + 1 , i ] [i-len+1,i] [ilen+1,i]等于模式串 [ 1 , l e n ] [1,len] [1,len]
我们考虑上一次计算对这次的贡献,已知对于文本串中第 i − 1 i-1 i1个的值为 a i − 1 a_{i-1} ai1,上一次计算结果为 x x x,此时可以发现,这次结果最大为 x + 1 x+1 x+1,并且对于这次结果 y y y,存在模式串 b b b b y − 1 = b x = a i − 1 b_{y-1}=b_{x}=a_{i-1} by1=bx=ai1(显然的),并且有 b y = a i b_y=a_i by=ai以及 b [ 1 , y − 1 ] = b [ x − y + 2 , x ] b[1,y-1]=b[x-y+2,x] b[1,y1]=b[xy+2,x]

也就是说,只要统计对于一个 x x x,找出 b b b [ 1 , x ] [1,x] [1,x]区间段的公共前后缀(以下称为border)就行了(公共前后缀,就是一对相同长度的前缀和后缀,满足前缀=后缀)

不难发现,border的border是border,如图
在这里插入图片描述
(有点丑,见谅)

这意味着,我们可以通过最长border求出所有border,我们命名最长border数组为nx数组

求nx数组跟匹配思路类似,不再赘述,何况也有许多讲的比我好的,我只是提供一种在模式串上求border的方法罢了
代码:

const int N=1e6+7;
int nx[N];
int kmp(char s[],char t[],int n,int m){if(m>n)return -1;for(int i=1,j=0;i<m;i++){while(j&&t[i]!=t[j])j=nx[j-1];nx[i]=(t[i]==t[j]?++j:0);}for(int i=0,j=0;i<n;i++){while(j&&s[i]!=t[j])j=nx[j-1];if(s[i]==t[j])if(++j==m)return i;}return -1;
}

http://www.ppmy.cn/embedded/137385.html

相关文章

Dinky控制台:利用SSE技术实现实时日志监控与操作

1、前置知识 1.1 Dinky介绍 实时即未来,Dinky 为 Apache Flink 而生,让 Flink SQL 纵享丝滑。 Dinky 是一个开箱即用、易扩展,以 Apache Flink 为基础,连接 OLAP 和数据湖等众多框架的一站式实时计算平台,致力于流批一体和湖仓一体的探索与实践。 致力于简化Flink任务开…

React核心概念与特点

React是由Facebook开发并维护的一个用于构建用户界面的开源JavaScript库。它以其独特的组件化架构、高效的性能优化以及灵活的状态管理方式&#xff0c;在前端开发领域占据了重要地位。本文将对React的核心概念、特点以及关键知识点进行全面解析&#xff0c;以帮助读者更好地理…

C++builder中的人工智能(27):如何将 GPT-3 API 集成到 C++ 中

人工智能软件和硬件技术正在迅速发展。我们每天都能看到新的进步。其中一个巨大的飞跃是我们拥有更多基于自然语言处理&#xff08;NLP&#xff09;和深度学习&#xff08;DL&#xff09;机制的逻辑性更强的AI聊天应用。有许多AI工具可以用来开发由C、C、Delphi、Python等编程语…

vue3中使用swiper的方法及版本兼容问题

Swiper官方文档 https://swiper.com.cn/ 前言 如果使用vue3开发尽量避免swiper6及以下版本(踩的坑很多)&#xff0c;我使用的swiper7.4.1 开发中vue总是会遇到版本兼容性问题&#xff0c;每次都要调半天&#xff0c;很头疼....废话不多说&#xff0c;直接上方法及代码。 1.首先…

一文总结java语法规则

1. 题记 Java是一门拥有较强语法规则的编程语言&#xff0c;本博文主要总结介绍java语言的java语法规则。 2. java语法规则 2.1 标识符&#xff08;Identifiers&#xff09; 定义&#xff1a;标识符是用来给变量、类、方法、接口等命名的字符序列。规则&#xff1a; –标识…

构建智能防线 灵途科技光电感知助力轨交全向安全防护

10月27日&#xff0c;在南京南站至紫金山东站间的高铁联络线上&#xff0c;一头野猪侵入轨道&#xff0c;与D5515次列车相撞&#xff0c;导致设备故障停车。 事故不仅造成南京南站部分列车晚点&#xff0c;还在故障排查过程中导致随车机械师因被邻线限速通过的列车碰撞而不幸身…

无人机+无人车+无人狗+无人船:互通互联技术探索详解

关于“无人机无人车机器狗&#xff08;注&#xff1a;原文中的“无人狗”可能是一个笔误&#xff0c;因为在实际技术领域中&#xff0c;常用的是“机器狗”这一术语&#xff09;无人船”的互通互联技术&#xff0c;以下是对其的详细探索与解析&#xff1a; 一、系统架构与关键…

API接口精准获取商品详情信息案例

在当今数字化时代&#xff0c;电子商务平台的蓬勃发展&#xff0c;使得商品信息的获取变得尤为重要。API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;作为连接前端用户界面与后端服务的桥梁&#xff0c;扮演着至关重要的角色。本文…