【板子】kmp #include iostream #include string #include vector using namespace std; // 求模式串p的next数组最长border vectorint getNext(const string p) { int n p.size(); vectorint next(n 1, 0); // next[1]~next[n] 对应长度1~n前缀 int j 0; for (int i 2; i n; i) { while (j 0 p[i - 1] ! p[j]) j next[j]; if (p[i - 1] p[j]) j; next[i] j; } return next; } // KMP匹配返回所有匹配起始位置1开头 vectorint kmpSearch(const string s, const string p, const vectorint next) { vectorint res; int n s.size(), m p.size(); int j 0; for (int i 1; i n; i) { while (j 0 s[i - 1] ! p[j]) j next[j]; if (s[i - 1] p[j]) j; // 完全匹配 if (j m) { res.push_back(i - m 1); // 左端点l1起始 j next[j]; } } return res; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); string s1, s2; cin s1 s2; auto next getNext(s2); auto pos kmpSearch(s1, s2, next); // 输出所有匹配位置 for (int x : pos) cout x \n; // 输出next[1]~next[m]空格分隔 int m s2.size(); for (int i 1; i m; i) { cout next[i] ; } return 0; }next特性len-next[len]是最小循环节优化失配数组#include iostream #include string #include vector using namespace std; vectorint getNext(const string p) { int n p.size(); vectorint next(n 1, 0); int j 0; for (int i 2; i n; i) { while (j 0 p[i - 1] ! p[j]) j next[j]; if (p[i - 1] p[j]) j; next[i] j; } return next; } // 生成nextval优化数组 vectorint getNextVal(const string p, const vectorint next) { int n p.size(); vectorint nextval(n 1, 0); nextval[1] 0; for (int i 2; i n; i) { int k next[i]; while (k 0 p[i - 1] p[k]) k next[k]; nextval[i] k; } return nextval; } // KMP匹配改用nextval vectorint kmpSearchVal(const string s, const string p, const vectorint nextval) { vectorint res; int n s.size(), m p.size(); int j 0; for (int i 1; i n; i) { while (j 0 s[i - 1] ! p[j]) j nextval[j]; if (s[i - 1] p[j]) j; if (j m) { res.push_back(i - m 1); j nextval[j]; } } return res; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); string s1, s2; cin s1 s2; auto next getNext(s2); auto nextval getNextVal(s2, next); auto pos kmpSearchVal(s1, s2, nextval); for (int x : pos) cout x \n; int m s2.size(); for (int i 1; i m; i) cout nextval[i] ; return 0; }KMP 完整原理分三层讲问题、暴力缺陷、next 数组、匹配流程、nextval 优化一、原始问题字符串模式匹配给定文本串 S长 n、模式串 P长 m找出 S 中所有 P 出现的位置。暴力匹配缺点两个指针 i文本、j模式匹配相等\(i,j\)失配i 回退到 \(i-j2\)j 归零 最坏复杂度 \(O(nm)\)如SaaaaaaaPaaab大量重复比较浪费时间。KMP 核心目标失配时文本指针 i 不回退只让模式指针 j 跳到最优位置整体线性 \(O(nm)\)。二、核心概念Border前缀函数 /next 数组1. 定义对模式串前 i 个字符组成的前缀 \(P[1,i]\)真前缀不包含最后一位真后缀不包含第一位\(next[i]\) 最长的长度 k满足前 k 位 后 k 位\(ki\)这个长度叫Border。例\(Pabcab\)长度 5 前缀a ab abc abca abcab 后缀b ab cab bcab abcab 最长相等真前后缀是ab长度 2 → \(next[5]2\)。2. next 数组求解逻辑1-based和你板子统一j 记录上一个前缀的最长 border 长度\(next[1]0\)单个字符无真前后缀i 从 2 遍历到 m若 \(P[i-1] \ne P[j]\)\(jnext[j]\) 回溯直到 \(j0\)匹配相等\(j\)\(next[i]j\)。 全程只前进不回退\(O(m)\) 求出 next。3. Border 的关键作用KMP 灵魂当匹配到 \(P[j]\) 和文本失配时 \(P[1,j-1]\) 是已经匹配成功的一段不需要全部重比。 利用 \(next[j-1]k\)说明 \(P[1,k] P[j-k,j-1]\)直接把 j 跳到 k文本指针 i 不动。举例 \(Pabcabc\)匹配到第 6 位失配\(next[6]3\)直接让 \(j3\)拿 \(P[3]\) 继续和当前文本字符对比省去从头匹配。三、KMP 匹配主流程设文本 S模式 Pi 文本下标j 模式下标循环遍历文本每个字符 \(S[i]\)失配且 \(j0\)\(jnext[j]\)若字符相等\(i,j\)当 \(jm\)模式完全匹配记录匹配起点\(jnext[j]\) 寻找重叠匹配比如aaaa中aa会多次匹配。全程 i 只增不减总复杂度 \(O(nm)\)。四、nextval优化失配数组原理问题普通 next 存在无效跳转例 \(Paaaaa\)\(next[4]3\)若 \(P[4]P[3]a\) 失配时跳到 \(j3\)字符还是 a依然失配多一次无用判断。nextval 优化规则对每个 i\(knext[i]\)若 \(P[i-1] P[k]\)继续令 \(knext[k]\)直到字符不等或 \(k0\)\(nextval[i]k\)。作用失配时一步跳到字符不同的位置减少比较次数卡常专用。五、拓展Border 衍生知识点1. 最小循环节字符串总长 L最长 border \(knext[L]\)循环节长度 \(dL-k\)。若 \(L \% d 0\)整个串由 \(L/d\) 个相同子串重复否则最小循环节是自身。 例abcabcabc\(L9,next[9]6,d3\)可由abc重复 3 次构成。2. 所有 Border 数量cnt 数组动物园题\(cnt[i]\) 前缀 i 所有合法 border 的总个数 递推式\(cnt[i] cnt[next[i]] 1\) 含义最长 border 最长 border 的所有 border。3. 不重叠 bordernum 数组NOI 动物园要求 \(2k \le i\)前后缀不重叠用双指针维护最大合法 k\(num[i]cnt[k]\)最后累乘 \((num[i]1)\) 得答案。

相关新闻

最新新闻

学生党用 AI 辅助学习的正确姿势:从“抄答案”转向“深度理解”

学生党用 AI 辅助学习的正确姿势:从“抄答案”转向“深度理解”

Q:学生党如何正确用 AI 辅助学习?怎样才能避免沦为“抄作业”的工具? A: 1.分项结论 ① 核心数据与指标参数: 效率对比:传统低效的“直接复制答案”学习法,期末复习及知识点留存率仅为 15%&a…

2026/8/28 8:19:48
蓝桥杯冲刺:真题解析心法与进制转换、交换瓶子、博弈问题实战

蓝桥杯冲刺:真题解析心法与进制转换、交换瓶子、博弈问题实战

1. 赛前冲刺的“真题”价值:不止是刷题 距离蓝桥杯比赛还有最后几天,很多同学的状态可能和我当年一样:题库刷了不少,但心里还是没底,总觉得还差点什么。这时候,最常见的做法就是疯狂找“真题”来刷&#xf…

2026/8/28 8:19:48
蓝桥杯国赛真题解析:最长公共子序列(LCS)在蓝肽子序列问题中的应用

蓝桥杯国赛真题解析:最长公共子序列(LCS)在蓝肽子序列问题中的应用

1. 项目概述:从“蓝肽子序列”看国赛动态规划命题逻辑 看到“蓝肽子序列”这个题目,很多参加过蓝桥杯国赛或者正在备赛的同学可能会心一笑,或者眉头一紧。这确实是2020年第十一届蓝桥杯软件类国赛(C/C/Java组)的一道经…

2026/8/28 8:19:48
PNG隐藏水印揭秘:用Python解析C2PA与GUID标识

PNG隐藏水印揭秘:用Python解析C2PA与GUID标识

最近看到一条很有意思的消息:有人在逆向 Windows 11 上的“画图”和“照片”应用时发现,微软为本地 AI 生成或编辑过的图片加入了不可见的 GUID 水印。也就是说,你用记事本、画图工具生成的 AI 图片,表面看起来和普通图片没有任何…

2026/8/28 8:19:48
Level 4自动驾驶系统设计47——L4 架构设计 0

Level 4自动驾驶系统设计47——L4 架构设计 0

第 9 章:L4 级“异构三芯片”失效可用架构设计 9.1 核心算力组分布式部署:主/从双片冗余 SoC 跨芯片张量并行与全时数据交叉校验 9.1.1 自动驾驶全栈并网下的单芯算力断层与冗余重构 当自动驾驶系统演进至 Level 4 级全栈并网大模型(VLA/端到端基座模型)时,前级感知融合…

2026/8/28 8:19:48
Python networkx邻接矩阵可视化:从矩阵构建到布局优化的完整指南

Python networkx邻接矩阵可视化:从矩阵构建到布局优化的完整指南

1. 从邻接矩阵到可视化网络:一个被低估的起点在数据分析和算法研究的路上,我们经常和“图”打交道。无论是社交网络里的好友关系、知识图谱里的概念链接,还是交通网络里的站点连接,本质上都可以抽象成点和边的集合。而邻接矩阵&am…

2026/8/28 8:14:48