【算法】KMP算法

news/2024/9/28 15:58:20/

目录

1、暴力做法及优化

2、next数组的含义

3、匹配思路及代码

4、实现next数组

5、最终代码


kmp算法主要解决的是字符串匹配问题

1、暴力做法及优化

假设我们现在有一个长度为n的模式串p="aabaaf",一个长度为m的模板串s="aabaabaaf",p可能在s中有多次出现,要找出p在s中出现位置的起始下标,这里的p和s的下标都是从1开始的。

很容易想到的暴力做法就是外层遍历s,对于s中的每一个元素,都以其为起点区匹配p,当不匹配时就前往s的下一个元素,这样的时间复杂度是O(n*m)。实际上不需要回退到s的下一个位置,p也不需要重新从起始开始匹配

当从某一位开始不匹配时,因为前面的所有位置都是严格匹配的,所以是有一些额外信息在里面的,可以利用这些额外信息来减少枚举

2、next数组的含义

为了实现上面不匹配时的操作,需要定义一个next数组,next[i]表示的是p字符串中下标[1, i]这个子串的最长公共前后缀,以我们上面的p="aabaaf"为例

paabaaf
下标i123456
next[i]010120

前缀的意思就是包含首字符,不包含尾字符的所有子串
后缀的意思就是包含尾字符,不包含首字符的所有子串
像aabaaf这个字符串
前缀有a,aa,aab,aaba,aabaa
后缀有f,af,aaf,baaf,abaaf
next[1] = 0,此时子串是a,前缀为空集,后缀也为空集
next[2] = 1,此时子串是aa,前缀为a,后缀为a
next[3] = 0,此时子串是aab,前缀为a,aa,后缀为b,ab
next[4] = 1,此时子串是aaba,前缀为a,aa,aab,后缀为a,ba,aba
next[5] = 2,此时子串是aabaa,前缀为a,aa,aab,aaba,后缀为a,aa,baa,abaa
next[6] = 0,此时子串是aabaaf,前缀为a,aa,aab,aaba,aabaa,后缀为f,af,aaf,baaf,abaaf

3、匹配思路及代码

我们通过字符串p求出next数组后,就可以利用next数组来完成字符串匹配时的操作了

解释一下为什么当遇到不匹配的位置时,可以直接让j = next[j]。当s[i]!=p[j+1]时,说明p[1, j]和
s[i - j, i - 1]这两个区间是完全匹配的,next[i]表示的是p字符串中下标[1, i]这个子串的最长公共前后缀,next[j]的值就是[1, j]这个子串的前缀和后缀最长的相等长度,在这个题目中就是2,会发现2刚好是前缀末尾的下标,所以直接用前缀来替换后缀对前面字符串的匹配

    // 匹配原数组for (int i = 1, j = 0; i <= m; i++){while (j && s[i] != p[j + 1]) j = ne[j]; // 当不匹配时就一直回退,直到匹配或者j == 0if (s[i] == p[j + 1]) j++; // 如果回退到了匹配的位置,j++if (j == n) // p数组遍历完了{printf("%d ", i - n); // 打印起始位置j = ne[j]; // 遍历完成后回退到ne[j]的位置继续匹配}}

这里说一下为什么i从1开始,而j从0开始。i从1开始是因为s字符串是从下标1开始存储值的,j从0开始是因为最长公共前缀和可能是0,当j这个位置的最长公共前缀和是0时,j就会回退到0的位置,可以以此来特判j == 0时就不需要回退

4、实现next数组

前面我们介绍了next数组的含义,以及利用next数组去匹配的思路,现在我们介绍如何获得next数组

获得next数组实际上就是一个用p字符串自身与自身匹配的一个过程

我们使用i来表示后缀的末尾,j来表示前缀末尾

因为next[1]一定是0,一个字符既没有前缀也没有后缀,所以i是从2开始的。j从0开始

    // 构建next数组for (int i = 2, j = 0; i <= n; i++){while (j && p[i] != p[j + 1]) j = ne[j]; // 当不匹配时就一直回退,直到匹配或者j == 0if (p[i] == p[j + 1]) j++; // 如果回退到了匹配的位置,j++ne[i] = j;}

5、最终代码

#include <iostream>using namespace std;
const int N = 100010, M = 1000010;
char p[N], s[M];
int ne[N];
int n, m;
int main()
{cin >> n >> p + 1 >> m >> s + 1;// 构建next数组for (int i = 2, j = 0; i <= n; i++){while (j && p[i] != p[j + 1]) j = ne[j]; // 当不匹配时就一直回退,直到匹配或者j == 0if (p[i] == p[j + 1]) j++; // 如果回退到了匹配的位置,j++ne[i] = j;}// 匹配原数组for (int i = 1, j = 0; i <= m; i++){while (j && s[i] != p[j + 1]) j = ne[j]; // 当不匹配时就一直回退,直到匹配或者j == 0if (s[i] == p[j + 1]) j++; // 如果回退到了匹配的位置,j++if (j == n) // p数组遍历完了{printf("%d ", i - n); // 打印起始位置j = ne[j]; // 遍历完成后回退到ne[j]的位置继续匹配}}return 0;
}

http://www.ppmy.cn/news/1531557.html

相关文章

《机器学习》周志华-CH8(集成学习)

8.1个体与集成 集成学习(ensemble learning)通过构建并结合多个学习器来完成学习任务&#xff0c;有时也被称为多分类器系统&#xff0c;基于委员会的学习。 同质”集成“&#xff1a;只包含同种类型的个体学习器&#xff0c;同质集成中的个体学习器亦称“基学习器”&#xff0…

git rebase 调整提交顺序

今天在提交代码到gerrit上面后发现该笔提交之前有一笔本地加日志测试用的提交一起被带上去了: 1AC30902 (HEAD -> master) normal commit, modify xxx 82CC31A4 add test log 2364BBD1 normal commit2, modify yyy 其中&#xff0c;第二笔提交因为只是测试使用的&#xff0…

Caddy在CentOS 7的安装与使用

Caddy是一个用Go语言编写的灵活和强大的web服务器&#xff0c;配置简单&#xff0c;自动HTTPS&#xff0c;可以为站点提供更好的安全性和性能。 安装 yum install yum-plugin-copr yum copr enable caddy/caddy yum install caddy启动Caddy caddy start 验证是否启动 curl l…

Qt开发技巧(八)自带对话框的美化,内置快捷代码段,巧用匿名槽函数,另类动态换肤,资源动态加载

继续讲一些Qt开发中的技巧操作&#xff1a; 1.自带对话框的美化 Qt中有一些自带的对话框&#xff0c;比如文件选择对话框&#xff0c;颜色选择对话框等等&#xff0c;这些对话框看着跟系统的对话框没太大差别&#xff0c;实际这是Qt有意为之&#xff0c;为的是跟系统保持一致。…

AI大模型日报#0923:李飞飞创业之后首个专访、华为云+腾讯音乐发布昇腾适配方案

导读&#xff1a;AI大模型日报&#xff0c;爬虫LLM自动生成&#xff0c;一文览尽每日AI大模型要点资讯&#xff01;目前采用“文心一言”&#xff08;ERNIE-4.0-8K-latest&#xff09;、“智谱AI”&#xff08;glm-4-0520&#xff09;生成了今日要点以及每条资讯的摘要。欢迎阅…

一步一步丰富生成式语言模型系统

以下是这套生成式语言模型解决任务的流程图概述&#xff1a; #mermaid-svg-sRHDSMUMV1utrg2F {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-sRHDSMUMV1utrg2F .error-icon{fill:#552222;}#mermaid-svg-sRHDSMUMV1u…

宝塔搭建nextcould 30docker搭建onlyoffic8.0

宝塔搭建nextcould 宝塔搭建nextcould可以参考这两个博文 我搭建的是30版本的nextcould&#xff0c;服务组件用的是下面这些&#xff0c;步骤是一样的&#xff0c;只是版本不一样而已 nginx 1.24.0 建议选择nginx&#xff0c;apache没成功。 MySQL 8.0以上都可以 php 8.2.…

高度细化的SAGA模式实现:基于Spring Boot与RabbitMQ的跨服务事务

场景与技术栈 场景&#xff1a;电商系统中的订单创建流程&#xff0c;涉及订单服务&#xff08;Order Service&#xff09;、库存服务&#xff08;Inventory Service&#xff09;、支付服务&#xff08;Payment Service&#xff09;。 技术栈&#xff1a; Java 11 Spring Bo…