【五十一】【算法分析与设计】KMP 算法,KMP 算法的作用,KMP 算法流程,KMP 算法证明,KMP 算法代码

 

目录

KMP 算法的作用,解决的问题

KMP 算法的流程

Next 数组

KMP 算法正式过程

KMP 算法的证明过程

Next 数组的求法

Next 数组求法的证明过程

KMP 算法代码

结尾


 

KMP 算法的作用,解决的问题

1.

首先给你一个字符串 str,然后又给你一个字符串 match,请你再 str 的子串中找,是否存在字符串与 match 匹配,如果找到了返回该子串在 str 的开始位置下标,如果没有找到返回 -1。

2.

暴力解法,遍历所有子串需要 O(N*M)的时间复杂度,KMP 算法可以只用 O(N)时间复杂度解决这个问题。

KMP 算法的流程与证明过程

Next 数组

1.

对于 match 数组的每一个元素都有一个对应的数值,存储在 next 数组中。

2.

match[i]对应 next[i]。

3.

next[i]存储的值是,i 位置前面部分的最长公共前后缀的长度。

i 位置前面部分是指 0~i-1 区间。

例如 0~i-1 区间对应字符串为 abcabc。

前缀序列指的是 a,ab,abc,abca,abcab。

后缀序列指的是 c,bc,abc,cabc,bcabc。

公共前后缀长度是指,前后缀序列相同的长度,例如 a 与 c 前后缀序列不相同,ab 与 bc 前后缀序列不相同,abc 与 abc 前后缀序列相同,长度为 3,abca 与 cabc 前后缀序列不相同,abcab 与 bcabc 前后缀序列不相同。

因此最长公共前后缀长度为 3。

4.

人为规定 next[0]=-1,next[1]=0。

KMP 算法正式过程

3799f6b243d04c0e9876766d1ee603f9.png

1.

如果 str[i~X-1]全部与 match[0~Y-1]匹配成功,此时 X 与 Y 匹配失败,Y=next[Y],Y 回退到对应 next 存储的下标位置。

然后新的 Y 下标与 X 继续匹配。

2.

如果 next[Y]==-1,此时说明 Y==0,X++,然后新的 X 下标和 Y 继续匹配。

3.

如果 X 与 Y 匹配成功,X++,Y++,新的 X 与新的 Y 继续匹配。

4.

直到 XY 其中一个越界,如果 X 越界说明 Y 还没有匹配完,后面没有字符了,说明匹配失败,返回 -1。

如果 Y 越界,说明 Y 匹配完了,匹配成功,对应的 str 匹配子串开始下标位置是 X-Y。

KMP 算法的证明过程

c5e41050f1474404bd77a48ae41691d3.png

1.

如果 str[i~X-1]全部与 match[0~Y-1]匹配成功,此时 X 与 Y 匹配失败,Y=next[Y],Y 回退到对应 next 存储的下标位置。

然后新的 Y 下标与 X 继续匹配。

1.

A 部分和 B 部分相同,C 部分与 B 部分相同,说明 A 部分和 C 部分相同,Y 回退到 next[Y]位置,相当于已经匹配完 AC 部分接下来匹配红色 Y 与 X 位置元素。

08b888b9317141a0a5f6a239b6f65807.png

2.

为什么 A 部分前面都可以不用考虑?

假设 A 部分前面开始匹配可以匹配成功,那么蓝色框框部分就是匹配成功的子串,上面蓝色部分 C 对应下面蓝色部分 C 是相同的,上面蓝色部分前面一段 C 和绿色框框 D 是相同的,也就是下面绿色 D 和蓝色 C 是相同的,那么 Y 的 next[Y]得到了一个更大的长度,我们 next[Y]最长公共前后缀是 BC 部分,现在推出一个更长的公共前后缀,推出矛盾,说明 A 部分前面都不用考虑。

2f772e972f08470fbfdd74a06e36d249.png

 

Next 数组的求法

ec2650d153884d0e82e8a7808cad9dc1.png

1.

假设 0~Y-1 的 next 都求完了,cn 是 Y-1 对应的 next 值。

如果 match[cn]==match[Y-1],next[Y]=cn+1。

2.

如果 match[cn]!=match[Y-1],cn=next[cn].

然后新的 cn 继续与 Y-1 进行判断。

3.

如果 next[cn]==-1,说明 cn==0,next[Y]=0。

4.

下一次计算的时候,cn 等于 Y-1 对应的 next 值,初始化。

Next 数组求法的证明过程

adf7fd5398c34538935be06ef42428fd.png

1.

首先 next[Y]最大是 A 的长度,当且仅当 match[next[Y-1]]==match[Y]的时候,取得。这是 next[Y]的极限。

不可能大于这个值,如果大于说明最长公共前后缀求错了,推出时矛盾的。

2.

如果 match[cn]!=match[y-1], cn=next[cn].

此时我们在判断紫色位置有没有可能是最长公共前后缀,也就是我们跳过了蓝色区间。也就是我们需要证明蓝色位置不可能是最长公共前后缀开始的位置。

同理,如果蓝色位置有可能成为答案,那么会推出最长公共前后缀求错了,推出矛盾,所以蓝色部分是不可能的区间位置。

3.以此类推....

KMP 算法代码

 
#include<bits/stdc++.h>
using namespace std;
class code01_KMP {
public:
        static int getIndexof(string str, string match) {
                if (str.empty() || match.empty() || str.size() < match.size())
                        return -1;
                int x = 0, y = 0;
                vector<int> next = getNextVector(match);
                while (x < str.size() && y < match.size()) {
                        if (str[x] == str[y]) {//如果相等往后移
                                x++;
                                y++;
                        } else if (next[y] != -1) {//如果不相等,y后退到next[y]位置
                                y = next[y];
                        } else {//如果next[y]==-1,即y==0,x++
                                x++;
                        }
                }//x-a+1=y+1--->a=x-y
                return y == match.size() ? x - y : -1;
        }
        static vector<int> getNextVector(string match) {
                if (match.size() == 1) return { -1 };
                vector<int> next(match.size());
                next[0] = -1;
                next[1] = 0;

                int i = 2;//从下标为2位置开始计算next
                int cn = 0;//i-1位置的next数值
                while (i < next.size()) {
                        if (match[i - 1] == match[cn]) {//如果i-1位置字符与cn相等,cn是某个公共前后缀长度,cn+1表示next[i]
                                next[i++] = ++cn;
                        } else if (next[cn] != -1) {//如果next[cn]!=-1,cn=nect[cn]
                                cn = next[cn];
                        } else {//如果nect[cn]==-1,cn不能等于nect[cn],next[i]==cn==0
                                next[i++] = 0;
                        }

                }

                return next;
        }
        static string getRandomString(int possibilities, int size) {//0-25
                srand(time(NULL));
                //string ans("", rand() % (size + 1));
                string ans("", size);
                for (int i = 0; i < ans.size(); i++) {
                        ans[i] = rand() % (possibilities + 1) + 'a';
                }
                return ans;
        }

};

int main() {
        int possibilities = 5;
        int strSize = 20;
        int matchSize = 5;

        cout << "test begin" << endl;
        string str = code01_KMP::getRandomString(possibilities, strSize);
        string match = code01_KMP::getRandomString(possibilities, matchSize);
        cout << "str:" << str << endl;
        cout << "match:" << match << endl;
        int pos = code01_KMP::getIndexof(str, match);
        if (pos != -1)
                cout << "匹配成功! 开始下标:" << code01_KMP::getIndexof(str, match) << endl;
        else cout << "匹配失败!" << endl;

}

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

 

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

 

谢谢您的支持,期待与您在下一篇文章中再次相遇!

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/557339.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mPEG-Succinimidyl Carboxyl Methyl ester,135649-01-3可以制备出多种生物成像试剂

【试剂详情】 英文名称 mPEG-SCM&#xff0c;Methoxy PEG SCM&#xff0c; mPEG-Succinimidyl Carboxyl Methyl ester 中文名称 聚乙二醇单甲醚琥珀酰亚胺乙酸酯&#xff0c; 甲氧基-聚乙二醇-琥珀酰亚胺乙酸酯 CAS号 135649-01-3 外观性状 由分子量决定&#xff0c;液体…

交流电220V转9V直流电芯片WT5105

交流电220V转9V直流电芯片WT5105 WT5105设计一个电路。电路的输入端连接到220V交流电&#xff0c;通过一个整流桥进行整流&#xff0c;将交流电转换为脉冲直流电。然后&#xff0c;经过电容滤波后&#xff0c;得到较为平滑的直流电。这个直流电进入WT5105的输入端。 在WT5105的…

揭秘1688选品高阶玩法,90%的人都没注意到(下篇)

店雷达继续为各位商家揭秘1688选品7大高阶玩法&#xff0c;错过前4个选品场景思路干货的商友们可以点击上篇查看哦。希望帮助各位找到符合自己选品方向&#xff0c;提供一些新的思路帮助。☛《揭秘1688选品高阶玩法&#xff0c;90%的人都没注意到&#xff08;上篇&#xff09;》…

2W 6KVDC 隔离双输出 DC/DC 电源模块——TPJ-2W 系列,可以用于医疗仪器和设备中

TPJ-2W一款有超高隔离电压的电源模块&#xff0c;主要用于隔离度要求高的如医疗仪器和设备&#xff0c;特别在安全设备的应用中起着相当重要的作用&#xff0c;它的绝缘设计完全能满足对隔离电压要求超过6KVDC的应用&#xff0c;在额定负载2W的情况下&#xff0c;工作温度范围为…

鸿蒙原生应用元服务-访问控制(权限)开发场景与权限声明

一、场景介绍 应用的APL&#xff08;Ability Privilege Level&#xff09;等级分为normal、system_basic和system_core三个等级&#xff0c;默认情况下&#xff0c;应用的APL等级都为normal等级。权限类型分为system_grant和user_grant两种类型。 二、配置文件权限声明 应用需要…

基于springboot+vue花店商场管理系统

项目介绍&#xff1a; 基于springbootvue花店商场管理系统 开发系统&#xff1a;Windows 架构模式&#xff1a;MVC/前后端分离 JDK版本&#xff1a;Java JDK1.8 开发工具&#xff1a;IDEA 数据库版本&#xff1a; mysql8.0 数据库可视化工具&#xff1a; navicat 服务器&#…

腾讯EdgeOne产品测评体验—更快更强更安全,安全我选EdgeOne

腾讯EdgeOne产品测评体验—更快更强更安全&#xff0c;安全我选EdgeOne 王婆的瓜可甜&#xff1f; 自 23 年 8 月份 EdgeOne 开放订阅套餐后&#xff0c;腾讯云用户使用 EdgeOne 来为自己网站进行加速和防护的站点数量&#xff0c;呈现爆发式增长趋势。 金融服务业受到的 Web…

固体矿产资源储量分类GBT17766-2020

1999分类标准采用三轴体系划分资源量与处理&#xff0c;表达复杂、经济意义划分过细、实用性不强 虽然不再采用”三轴“表达方式&#xff0c;但依然考虑地质可靠程度、经济意义、可行性评价 矿产资源勘查&#xff1a;通常依靠地球科学知识&#xff0c;运用地质填图&#xff0…

分享4款免费ai绘画工具!

随着人工智能技术的飞速发展&#xff0c;AI绘画工具已经逐渐走入了我们的日常生活。这些工具不仅能够简化绘画过程&#xff0c;更能让普通人体验到艺术创作的乐趣。今天&#xff0c;我们就来盘点一下那些值得一试的免费AI绘画工具&#xff0c;看看它们如何让我们的创作欲望得到…

ABAP - LRAW类型转换为Xstring再转换为String

比如我想取出表SWWCNTP0里的DATA字段里的值&#xff1a; 那么可以用已有的含有LRAW字段的结构去放要取的数据&#xff1a;比如下面代码里的lt_data就是type table of 这个结构 取出来的数据&#xff0c;放到一个只含有LRAW的表里去&#xff08;lt_xml&#xff09; 取数的时候&a…

3D模型格式转换工具HOOPS Exchange:3D CAD数据的快速导入与导出

在当今的工程设计领域中&#xff0c;快速且可靠地处理3D CAD数据是至关重要的。HOOPS Exchange SDK通过提供一组C软件库&#xff0c;为开发团队提供了实现这一目标的有效工具。 什么是HOOPS Exchange&#xff1f; HOOPS Exchange是一组C软件库&#xff0c;旨在为开发团队提供…

【复习笔记】reeRTOS(七) 二值信号量和计数信号量

本文是FreeRTOS复习笔记的第七节&#xff0c;信号量。 上一篇文章&#xff1a; 【复习笔记】FreeRTOS(六) 队列操作 文章目录 一、信号量分类二、二值信号量2.1.实验设计2.2.测试例程2.3.实验效果 三、计数信号量3.1.实验设计3.2.测试例程3.3.实验效果 一、信号量分类 信号量是…

盲盒新风潮:从玩具到文化符号的转变

亲爱的朋友们&#xff0c;我是微三云的周丽&#xff0c;一名专注于私域电商模式创新的探索者。 随着互联网和电子商务的迅猛发展&#xff0c;商业模式不断创新&#xff0c;盲盒电商作为其中的一种新兴形式&#xff0c;正逐渐引起人们的关注。盲盒电商不仅仅局限于传统的日用品…

【电控实现5.1】

标幺系统 vb&#xff1a;峰值

【Node.js】 fs模块全解析

&#x1f525;【Node.js】 fs模块全解析 &#x1f4e2; 引言 在Node.js开发中&#xff0c;fs模块犹如一把万能钥匙&#xff0c;解锁着整个文件系统的操作。从读取文件、写入文件、检查状态到目录管理&#xff0c;无所不能。接下来&#xff0c;我们将逐一揭开fs模块中最常用的那…

【C++】string的使用

目录 1、为什么学习string类&#xff1f; 2、标准库中的string类 2.1 string类 2.2 string类的常见接口声明 2.2.1 string类的常见构造 ​编辑 2.2.2 string类对象的访问及遍历操作 2.2.3 string类对象的容量操作 2.2.4 string类对象的修改操作 ​编辑 1、为什么学习s…

CERLAB无人机自主框架: 2-动态目标检测与跟踪

前言&#xff1a;更多更新文章详见我的个人博客主页【MGodmonkeyの世界】 描述&#xff1a;欢迎来到CERLAB无人机自主框架&#xff0c;这是一个用于自主无人飞行器 (UAV) 的多功能模块化框架。该框架包括不同的组件 (模拟器&#xff0c;感知&#xff0c;映射&#xff0c;规划和…

gemini国内能用吗

gemini国内能用吗 虽然 Gemini 的具体功能和性能还未完全公开&#xff0c;但基于 Google 在 AI 领域的强大背景和技术实力&#xff0c;已经火出圈了&#xff0c;很多小伙伴已经迫不及待想了解一下它有什么优势以及如何快速使用上 首先我们来讲一下gemini的优势 多模态能力&a…

美摄智能视频创作平台,满足企业个性化的创作需求

视频已成为企业传播信息、展示品牌、吸引客户的重要手段&#xff0c;传统的视频制作方式往往耗时耗力&#xff0c;且效果不佳。美摄科技凭借其深厚的技术积累和创新能力&#xff0c;推出了面向企业的智能视频创作平台解决方案&#xff0c;助力企业轻松实现高质量的视频制作与传…

5 CatBoost模型

目录 1 背景 2 原理 2.1 类别特征处理 2.1.1 传统目标编码&#xff1a; TS 2.1.2 Greedy TS 2.1.3 ordered TS编码 2.1.4 CatBoost处理Categorical features总结 2.2.预测偏移处理 2.2.1 梯度无偏估计 2.3 树的构建​​​​​​​ 3 优缺点 优点 4 代码 1 背景 终于…
最新文章