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

KMP算法

引入

给出两个字符串 \(s_1\)\(s_2\),若 \(s_1\) 的区间 \([l, r]\) 子串与 \(s_2\) 完全相同,则称 \(s_2\)\(s_1\) 中出现了,其出现位置为 \(l\)
现在请你求出 \(s_2\)\(s_1\) 中所有出现的位置。

定义一个字符串 \(s\) 的 border 为 \(s\) 的一个\(s\) 本身的子串 \(t\),满足 \(t\) 既是 \(s\) 的前缀,又是 \(s\) 的后缀。
对于 \(s_2\),你还需要求出对于其每个前缀 \(s'\) 的最长 border \(t'\) 的长度。

思路

1.计算答案

容易想到暴力做法,从第一位开始枚举,如果包含则 \(ans+1\),接着从第二位开始,以此类推……时间复杂度为 \(O(nm)\)

我们观察哪里可以优化,可以发现第二层的 \(m\) 是无法优化的,只能优化外层的 \(n\)。其实没有必要从 \(1\) 枚举到 \(n\),不然会有重复比较的部分,比如:(这张图好像画错了,懒得画了,是这个意思就行)
image

所以 \(Knuth\) 发明了一个 \(fail\) 表(失败回退表)。\(fail_i\) 定义为最长的前缀后缀相等长度值(即题面的 border),如下图计算:
image

有了这个失败回退表,那么就很好做了,依次匹配,如果有不符合的就回退就好了:

Tips:
1.回退表是 \(b\) 字符串的。
2.\(j\) 表示的是已匹配的长度,而不是当前匹配的是哪一位

for(int i=1;i<=n;i++){while(j&&b[j+1]!=a[i]) j=fail[j];//回退if(b[j+1]==a[i]) j++;if(j==m){//如果包含cout<<i-m+1<<"\n";j=fail[j];}
}

2.计算 fail 表

那么我们如何计算这个 fail 表,容易发现 fail 表除了 0 以外,其他的数字一定是连续递增的。
所以我们初始化 \(fail_1 = 0\),用类似于计算答案的方法计算 \(fail\) 表。

fail[1]=0;
for(int i=2;i<=m;i++){while(j&&b[j+1]!=b[i]) j=fail[j];//匹配不了就回退if(b[j+1]==b[i]) j++;//是否匹配fail[i]=j;
}

两者合起来就是 KMP 算法了。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define PII pair<int,int>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int N=1e6+5;
char a[N],b[N];
int fail[N],n,m;
signed main()
{//freopen(".in","r",stdin);//freopen(".out","w",stdout);ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>(a+1);cin>>(b+1);n=strlen(a+1),m=strlen(b+1);int j=0;fail[1]=0;for(int i=2;i<=m;i++){while(j&&b[j+1]!=b[i]) j=fail[j];if(b[j+1]==b[i]) j++;fail[i]=j;}j=0;for(int i=1;i<=n;i++){while(j&&b[j+1]!=a[i]) j=fail[j];if(b[j+1]==a[i]) j++;if(j==m){cout<<i-m+1<<"\n";j=fail[j];}}for(int i=1;i<=m;i++){cout<<fail[i]<<" ";}return 0;
}
http://www.jsqmd.com/news/548534/

相关文章:

  • SViT实战:如何在PyTorch中实现超令牌采样的视觉转换器(附完整代码)
  • NOKOV动捕软件实战:如何用XINGYING快速创建刚体与人体Markerset(附常见问题解决)
  • python-flask-djangol框架的地方特色美食分享系统 餐厅美食推荐预订系统
  • 2026年主流GEO优化工具深度测评:从技术到效果的客观分析 - 小白条111
  • 分享一段豆包分享给我的话
  • 做一个DApp到底要多少钱?2026年真实成本逻辑(很多人都算错了)
  • MAI-UI-8B实战:小白也能用的GUI设计AI,一键生成HTML/CSS
  • 宝塔面板ClickHouse安装避坑指南:从Docker网络到密码配置的完整流程
  • 2026知识付费平台选择指南:学习者与创作者如何各取所需
  • 嵌入式图像处理实战:中值滤波VS均值滤波在STM32上的性能对比(附代码)
  • 解锁浏览器无限潜能:Greasy Fork开源脚本平台深度解析
  • [配置安全]:ComfyUI-Manager敏感数据防护的系统化实施指南
  • ReadMe.md
  • Windows系统下OpenSSL的安装、配置与常见避坑指南
  • nli-distilroberta-base实际案例:智能写作助手中的论点-论据逻辑支撑度实时反馈
  • AI赋能技能创建:让快马平台智能生成你的个性化学习规划系统
  • 净化门厂家哪家好?3家口碑实力双在线的选择指南
  • python-dateutil - 强大的日期时间解析与计算工具
  • 矿用电液控系统摄像仪护套连接器 DLJ01(850)参数
  • 次元画室一键部署教程:Python环境快速配置与模型启动
  • 华为交换机Netstream实战:如何用一条命令快速定位异常流量源IP
  • 2026年海狮租赁公司推荐:济宁市硕翊展览策划有限公司,小马戏表演租赁/萌宠租赁/动物租赁公司精选 - 品牌推荐官
  • AI读脸术作品集:看看模型如何识别不同人脸的属性
  • 修复wlanapi.dll不重装系统:IT运维人员的高效排查手册
  • YOLOE医疗影像检测实战:用文本提示快速定位病灶区域
  • LangFlow实战案例分享:智能问答助手工作流搭建全过程
  • GESP认证C++编程真题解析 | 202503 一级
  • EdgeRemover技术揭秘:彻底解决Windows Edge卸载难题的智能方案
  • 新闻推荐系统中的冷启动难题:阿里天池项目中的解决方案与实战代码
  • 鸣潮工具箱:3步解决游戏卡顿,让帧率提升60%的终极指南