当前位置: 首页 > news >正文

【杂乱笔记】Kmp字符串匹配算法

KMP 算法逻辑

  1. 构建 next 数组
    • 初始化 next 数组,用于存储每个位置的最长相同前后缀长度。
    • 遍历模式字符串patt
      • 如果当前字符与前缀字符匹配,增加前缀长度,并更新 next 数组。
      • 如果不匹配,使用 next[prefix\_len - 1] 回退到上一个可能的前缀长度,继续比较。
  2. 字符串匹配
    • 初始化两个指针 ij,分别指向文本 text 和模式 pattern 的开头。
    • 遍历文本:
      • 如果 text[i]pattern[j] 匹配,移动 ij
      • 如果 j 达到模式长度,说明匹配成功,记录匹配起始位置。
      • 如果不匹配且 j > 0,使用 next[j - 1] 回退 j,继续比较。
      • 如果 j == 0,仅移动 i
  3. 返回结果
    • 如果找到匹配,返回起始索引。
    • 如果没有匹配,返回 -1。

Next数组计算中,如果遇到当前字符与前缀字符不匹配的情况,那么就需要重新在前面遍历的内容中寻找次长的最长相同前后缀(对应代码为prefix_len = next[prefix_len - 1];),之后再与当前字符进行匹配(下一次while循环中的 if (patt[i] == patt[prefix_len])),如果还是匹配不上,那么就再再去之前的最长相同前后缀再次比较。

eg:

某一patt如下:

PattABCABD
Next000120

在匹配D时,我们当前的最长前后缀为AB,这时候通过代码prefix_len = next[prefix_len - 1];,我们相当于是去第一个AB中重新匹配,结果发现还是不匹配并且Next数组对应为0,所以DNext就为0。

#include <iostream>
#include <vector>
#include <string>using namespace std;vector<int> buildNext(const string& patt) {int m = patt.size();vector<int> next(m, 0);int prefix_len = 0;int i = 1;while (i < m) {if (patt[i] == patt[prefix_len]) {prefix_len++;next[i] = prefix_len;i++;} else {if (prefix_len != 0) {prefix_len = next[prefix_len - 1];} else {next[i] = 0;i++;}}}return next;
}int KMPsearch(const string& text, const string& pattern) {vector<int> next = buildNext(pattern);int i = 0; // text 的索引int j = 0; // pattern 的索引int n = text.size();int m = pattern.size();while (i < n) {if (text[i] == pattern[j]) {i++;j++;}if (j == m) {return i - j; // 匹配成功,返回起始索引} else if (i < n && text[i] != pattern[j]) {if (j != 0) {j = next[j - 1];} else {i++;}}}return -1; // 未找到匹配
}int main() {string text = "ababcabcabababd";string pattern = "ababd";int index = KMPsearch(text, pattern);if (index != -1) {cout << "Pattern found at index: " << index << endl;} else {cout << "Pattern not found" << endl;}return 0;
}

补充:前缀函数

此为字符串匹配的另一算法,通过简单转换即可转换为Kmp算法。

  • pi数组的定义:p[i]表示第i个前缀的最长匹配的真前、后缀的长度。
  • len=pi[len-1];这个解释和上述一样,就是寻找一个类似于回文的字符串。
vecotr<int>pi (str.size(),0);
for(int i=1;i<str.size();i++){int len=pi[i-1];while(len!=0&&str[i]!=str[len]){len=pi[len-1];}if(str[i]==str[len]){p[i]=len+1;}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 鸿萌数据恢复服务:SQL Server 中的“PFS 可用空间信息不正确”错误
  • XSS游戏
  • HTTP范围放大攻击简记
  • 三丰云免费服务器
  • 如何使用midjourney?MidJourney订阅计划及国内订阅教程
  • Java Instance(实例)的创建过程
  • SpringCloud天机学堂:分布式任务调度
  • 前端不同项目使用不同的node版本(Volta管理切换)
  • 超详细排序汇总--插入排序类,选择排序类,交换排序类,归并排序,非比较排序
  • (七)Flink Watermark
  • leetcode108.把升序数组转换成二叉搜索树
  • 【前端】VUE动态引入组件 通过字符串动态渲染模板 动态生成组件
  • 【ubuntu24.04】k8s 部署5:配置calico 镜像拉取
  • 【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(十二)
  • 目标检测 | yolov6 原理和介绍
  • 《Java编程思想》读书笔记-对象导论
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Django 博客开发教程 8 - 博客文章详情页
  • Effective Java 笔记(一)
  • Git同步原始仓库到Fork仓库中
  • Java 23种设计模式 之单例模式 7种实现方式
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • sessionStorage和localStorage
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 回顾2016
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 微信小程序开发问题汇总
  • 《码出高效》学习笔记与书中错误记录
  • 【干货分享】dos命令大全
  • 阿里云ACE认证之理解CDN技术
  • #git 撤消对文件的更改
  • #Linux(make工具和makefile文件以及makefile语法)
  • #QT(一种朴素的计算器实现方法)
  • (k8s中)docker netty OOM问题记录
  • (二)hibernate配置管理
  • (十)c52学习之旅-定时器实验
  • (十)T检验-第一部分
  • (十六)Flask之蓝图
  • (五)activiti-modeler 编辑器初步优化
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)shell中括号的特殊用法 linux if多条件判断
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .Net Remoting常用部署结构
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • @Resource和@Autowired的区别
  • [\u4e00-\u9fa5] //匹配中文字符
  • []T 还是 []*T, 这是一个问题
  • [2021 蓝帽杯] One Pointer PHP
  • [4.9福建四校联考]
  • [ABC294Ex] K-Coloring
  • [AI aider] 打造终端AI搭档:Aider让编程更智能更有趣!