「字符串」前缀函数|KMP匹配:规范化next数组 / LeetCode 28(C++)

前缀函数与KMP算法 前缀函数、KMP、前缀出现的次数 阅读详情

目录

概述

思路 

核心概念:前缀函数

1.前缀函数

2.next数组

1.考研版本

2.竞赛版本

 算法过程

构建next数组

匹配过程

复杂度 

Code


概述

为什么大家总觉得KMP难?难的根本就不是这个算法本身。

在互联网上你可以见到八十种KMP算法的next数组定义和模式串回滚策略,把一切都懂得特别混乱。很多时候初学者的难点根本不在于这个算法本身,而是它令人痛苦的百花齐放的定义。

有的next数组从0下标开始,有的从1开始;有的表示不包括本字符的前面部分的真前后缀,有的表示包括本字符的的前后缀,有的回滚+1,有的不+1,而他们却总是忽略这些异同,自顾自地讲KMP的匹配问题。初学者看到这直接傻了眼:随便挑两个视频或者文章,他们的定义和递推手段都不一样,让理解难度雪上加霜。

下面我们来先从字符串匹配讲起,想一想什么样的next数组定义才最适合这个算法本身。

LeetCode 28:

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1 。

示例 :

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

*注意*: 接下来我们将称呼haystack为主串,needle为模式串。


思路 

最普通的暴力算法总是在匹配失败后将主串指针i回滚到开始匹配的位置,模式串指针j回滚到0,然后在一轮for循环结束后执行i++操作来跳过这个匹配失败的位置。来看看Code。

class Solution {
public:
    int strStr(string haystack, string needle) {
        const int n=haystack.size();
        const int m=needle.size();
        for(int i=0;i<n;i++){
            if(haystack[i]==needle[0])
            for(int k=i,j=0;k<n;k++){
                if(haystack[k]==needle[j])j++;
                else break;
                if(j==m)return i;
            }
        }
        return -1;
    }
};

来想一想:都回滚j了,为什么还回滚i?难道就因为有一个字符匹配失败了就放弃前面所有的努力吗?

至少在最后的失败字符之前,我们匹配成功了。这意味着:

模式串为pattern,主串为main
                           j
pattern[j]  a  b  c  a  b  f  g
            √  √  √  √  √  ×
   main[i]  a  b  c  a  b  k  v  q  x  t
                           i

至少在'f'字符与'k'字符对比之前,我们的匹配成功了。

这意味着,main函数的此前部分和pattern的此前部分一一对应,这一部分字符串我们称之为str1。

这时候的一个独到之处就是:

在这段主串和模式串共同的[模式串begin,失配位置y)的str1中,任取这段字符之中的任意位置x,从x开始,一直到匹配失败的位置之前,模式串与主串都相同,这部分[x,y)的子串我们称为str2。

即:str2是str1的一个后缀子串

那我们如果可以有一个特殊的回滚模式串指针j的手段:不回滚到模式串最开始,而是回滚到模式串的某个位置t,把[模式串begin,某位置t)称为str3,而它与str2相同。

是的,我们要找一个模式串的头部子串,它与模式串的某个尾部字串是相同的。

结合例子感受一下:

模式串为pattern,主串为main
                           
           ┌str3┐ j<-------j
pattern[j] |a  b  c  a  b |f  g
           |        └str2┘| 
           |√  √  √  √  √ |
           |        ┌str2┑|
   main[i] |a  b  c  a  b |k  v  q  x  t
           └----str1------┘i

这样看还是不够清晰,我们把j的移动形象理解成模式串的移动。

模式串为pattern,主串为main
                           
                    ┌str3┐ j<-------j
pattern[j]           a  b  c  a  b  f  g
                             └str2┘ 
                     √  √
                    ┌str2┑
   main[i]  a  b  c  a  b  k  v  q  x  t
           └----str1-----┘ i

接下来我会用前后缀的语言代替“某某部分”:

//这是对前后缀的解释,如果你了解,可以跳过
对于一个字符串
begin                back
  a b a c d x f a c a d
  ---->           ---->
  前缀             后缀    //*注意*:前后缀的字符顺序都是从前向后
前缀是从[begin,x]的任意子字符串 真前缀的x不等于back
后缀是从 [x,back] 的任意子字符串 真后缀的x不等于begin

归纳一下:

当匹配到主串i位置同时模式串j位置,匹配失败时:

str2既是主串的[0,i)子串的一个后缀,又是模式串的[0,j)子字符串的一个后缀。

str3则是模式串中[0,j)子串的某个前缀,这个前缀与str2这个后缀相等。

因此,模式串中的str3能与模式串中的str2匹配,就意味着模式串中的str3与主串中的str2是天生匹配的。

形象理解:

           str3==str2
pattern -str3------str2-
        √√√√√√√√√√√√√√√×
main    -----------str2-
              ↓
pattern           -str3------str2-
                  √√√√√?
main    -----------str2-

那按理来说,这是一个模式串的自匹配问题:对于模式串的每个位置j,都有[0,j)子串,都要找到他们的最长相同真前后缀。

因此问题就转化成了:

枚举模式串的每个下标j,求出它的[0,j)子串的最长相同真前后缀,这样,当在任意位置匹配失败时,就可以知道j的回滚位置了,而i从不回滚。


核心概念:前缀函数

网络上各种奇异搞笑的next数组定义的根本来源是他们没搞懂前缀函数和next数组的区别。

前缀函数是一个独立的算法函数概念,next数组只是它针对于KMP算法的特化版本。

1.前缀函数

它写作π[i]或PM[i]。

定义:

给定一个长度为n的字符串,其前缀函数被定义为一个长度为n的数组π[n](或:PM[n])。 其中π[i]的意义是:字符串的[0,i]子串的最长相同真前后缀。

b90d787f5c374181be2f7b9bafd09dde.png

故有:

           j  0 1 2 3 4 5 6
string str[j] a b c a b c d
         π[j] 0 0 0 1 2 3 0

这是标准的前缀函数定义,他长度就是n,下标起始位置就是0,其他的任何一种next数组都是他的特化版本。

*注意*:我通常使用j来作为next数组和模式串的索引。

2.next数组

在KMP匹配算法中,π数组变成了next数组,有如下几种方案:

1.考研版本

①模式串、主串和next数组下标统一从1开始计数。[j]表示第j个字符处,而不是索引0代表第1个字符。next[0]值为-1。

②next[j]表示原字符串{s[1]...s[j-1]}的最长相同真前后缀长度,它记录在了next[j]。next[j]的值不包括第j个字符。

③回滚代码:j=next[j]+1。

例如上文的"abcabcd",如果当j=7失配时,由于next[j]=3,那么j会从4开始继续匹配,跳过了123。

           j  0  1  2  3  4  5  6  7
string str[j] n  a  b  c  a  b  c  d
      next[j] -1 0  0  0  0  1  2  3  
//n通常储存字符串的长度信息。

*注意*:你还会见到next[0]=0,且next数组整体+1的版本,它是另一个考研版本,只是将回滚代码的+1操作融入了next数组中,回滚代码:j=next[j],此处不再赘述。 

2.竞赛版本

事实上,在竞赛或者各大算法平台,字符串下标仍然从0开始,我们要为这个原则服务。

①字符串下标仍然从0开始,但我们仍然期望next数组下标从1开始。即主串与模式串从0开始,next数组从1开始,next数组长度比模式串大1,后续你会发现这样做的好处。

②next[j]表示原字符串*前j个字符*的最长相同真前后缀长度,它记录在了next[j],这里发生了错位。(next[0]=0,这样当j=0时执行回滚不会发生溢出,next[1]=0,第一个字符没有真先后缀)。

③回滚代码:j=next[j]。next数组错位的目的就是避免回滚代码发生+1-1的问题,这样能有效规避溢出。

例如上文的"abcabcd" ,如果当j=6失配时,next[j]==3,那么j会从3开始继续匹配,跳过了012。

即:j在某处失配时,它前面有j个字符,且这j个字符最长相同前后缀长度len储存在了next[j],可以快速访问next[j]得到j的回滚位置,回滚后恰好跳过len个字符。(我们总是期望在一轮for循环后j指向一个有待下一轮循环商榷的位置,不论是j++还是j=next[j],都是这样的。)

           j  0  1  2  3  4  5  6  7
string str[j] a  b  c  a  b  c  d \0
      next[j]    0  0  0  1  2  3  0  

 算法过程

*注意*:我们会以竞赛版本的KMP进行讲解。它稍微更改就可以变成考研版。

构建next数组

构建next数组才是KMP本身具有难度的地方。

推论:字符串增加一个字符,它的最长相同真前后缀至多+1。这个不起眼的推论是构建的核心。

但是我们可以将其总结为3点:

①next[0]=0,next[1]=0,这两个直接无视。随后发生for循环int i=1,j=0。

i向前探索;j即用于为next[i+1]赋值,又作为下标索引与向前探索的i遥相呼应:[0,j]与[i-j,i]匹配。

因此j同时代表着:[0,i]的公共前后缀长度数值,也是与i这个前方下标呼应的后方下标。

记得我们的定义是:next[j]表示原字符串*前j个字符*的最长相同真前后缀长度,i+1这个值才是[0,i]字符串的字符个数,因此j为next[i+1]赋值。

②当pattern[i]!=pattern[j],即位置i与位置j字符不匹配,通过while循环回滚j,如果仍失配,继续回滚,一直到j==0。

这一点是KMP的精髓所在:我们一边构建next数组,一边利用next数组回滚j。

这听起来很不可思议,但是注意:next数组是从前向后构建的,而回滚是向前的。这说明:我们在利用已经构建起的next数组进行回滚,而不会发生某种奇怪的冲突。

但是为什么用next数组回滚j呢?还记得next数组是干什么用的吗?它就是指示:当失配时,请从这里再试一试。不一定非要模式串与主串匹配才有失配,模式串自匹配时前缀不等于后缀也叫失配。我们回滚j就是期望将j回滚到可能与pattern[i]匹配的位置。

如果一直到j==0还失败,那就意味着不存在相同前后缀,那么为next[i+1]=j(即赋0值也是合理的了)

③判断pattern[i]是否等于pattern[j]。

如果因为j与i成功匹配而脱离while循环,那么j++,因为我们的最长相同前后缀+1。

void get_next(string&pattern,vector<int>&next){
        next[0]=0,next[1]=0;
        const int m=pattern.size();
        for(int i=1,j=0;i<m;i++){
            while(j&&pattern[j]!=pattern[i])j=next[j];
            if(pattern[j]==pattern[i])j++;
            next[i+1]=j;
        }
    }

匹配过程

匹配过程与构建过程极其类似。

主要是以下三点:

①当main[i]!=pattern[j],即在此处失配时,通过while循环回滚j,如果仍失配,继续回滚,一直到j==0。

②跳出while后判断main[i]是否等于pattern[j]。

由于脱离while要么是两者相等,要么不相等但j==0,那么:
if为真意味着:两者匹配成功,j++,i++。(两者在一轮循环后分别指向有待下一轮循环商榷的位置。)

if为假意味着:这一步就是判断出现j等于0且仍无法匹配的状况,那么认为这个i终究无法匹配,j停滞在0,随后放弃i的当前位置,i自增。

③判断j==m,这意味着完全匹配,返回i-m+1。(注意这里有个+1的细节:一轮for循环结束之前i++还未发生)

for(int i=0,j=0;i<n;i++){
    while(j&&main[i]!=pattern[j])j=next[j];
    if(main[i]==pattern[j])j++;
    if(j==m)return i-m+1;
}
return -1;

复杂度 

时间复杂度:O(n+m)

空间复杂度:O(m)

n:主串长度

m:模式串长度


Code

class Solution {
public:
    void get_next(string& pattern, vector<int>& next){
        const int m = pattern.size();
        for (int i = 1, j = 0; i < m; i++){
            while (j && pattern[j] != pattern[i])
                j = next[j];
            if (pattern[j] == pattern[i]) j++;
            next[i + 1] = j;
        }
    }
    int strStr(string haystack, string needle) {
        const int n = haystack.size(), m=needle.size();
        vector<int> next(m+1,0);
        get_next(needle, next);
        for (int i = 0, j = 0; i < n; i++){
            while (j && haystack[i] != needle[j])
                j = next[j];
            if (haystack[i] == needle[j]) j++; 
            if (j == m) return i - m + 1;
        }
        return -1;
    }
};

(如果你充分理解了本文,就会发现代码竟然如此直观) 。

KMP(1)-前缀函数(Prefix function)KMP的next函数 前言:   前段时间学习和字符串相关的算法,自然学到了KMP算法(解决单字符串匹配问题)。这里简单记录一下,方便以后回忆。  先给出二个名词,模式串(P), 文本串(T)。 比如ABC是否是ASDABC的子串,这里ABC是模式串(P),ASDABC是文本串,也叫被匹配串。引入:  KMP算法其实就是两个部分,①:前缀函数(求前缀数组)②:匹配部分。   那么什么是前缀函数呢??这是本篇文章的内容,... 阅读详情

相关推荐

奇安信算法笔试复盘:从KMP到安全场景,基础算法如何考察

数据结构与算法是所有技术面试的基石,尤其在网络安全领域,算法能力直接关系到流量分析、日志挖掘、威胁检测等核心业务的工程实现。针对奇安信春招算法方向的笔试复盘显示,其考察重点并非偏门难题,而是对KMP算法next数组手算、排序算法复杂度对比、动态规划与贪心边界判定、图论及并查集等基础功底的熟练度。这些考点不仅检验候选人的编码能力,更映射出安全场景中海量数据处理、实时告警聚类、恶意行为识别的实际需求。本文从通用算法原理出发,结合安全业务特色题型,梳理高频考点与工程实践细节,帮助求职者理解基础算法在安全厂商笔试中

weixin_30635053的博客 337

算法基础系列——字符串(二)前缀函数

前缀函数1、什么是前缀函数2、代码实现2.1、朴素写法2.2、优化写法 1、什么是前缀函数 我们通常用πππ表示前缀函数 2、代码实现 2.1、朴素写法 使得串下式中的字符串相同,j就是next数组的值。 s[0,j]=s[i−j+1,i] s[0,j]=s[i-j+1,i] s[0,j]=s[i−j+1,i] // C++ Version vector<int> prefix_function(string s) { int n = (int)s.length(); vector

一个憨憨写的胡言乱语 1467

【信息科学与工程学】【数据科学】数据科学领域 第六篇 算法设计 07 堆、栈、表、矩阵、集合、队列、数组、字符串、树、图、动态规划、结构体、元组的算法01

当前段必须包含所有字符的最后出现位置。1. 字符串分割成最多片段2. 基因序列功能域划分3. 文本段落划分4. 音频声道分离5. 图像色彩分区6. 社交网络社群划分7. 蛋白质结构域8. 音乐乐章分段9. 代码模块划分10. 章节划分特征:一次扫描,贪心确定边界。

weixin_49199313的博客 1273

前缀函数、KMP算法的实现

文章分享了字符串匹配相关的算法,前缀函数,以及将前缀函数的信息利用到极致的KMP算法,文章代码使用java来实现。

Erictr的博客 742

PSOC Creator 入门教程超详细

最近工作原因需要使用到赛普拉斯的一款芯片,奈何以前没有用过,所以趁这次也学习了一些简单的用法,总结一下,希望能帮到有需要朋友,因为网上关于这方面的文章少的可怜,详细点的更是少之又少!废话少说,正文开始.

qm_mq的博客 5747

Python | 集合(set)运算之intersection()

简介 在做力扣题的时候,有一个思路是要求解两个字符串的交集。 一般来说,求解交集的思路是遍历两个字符串,判断有无相等,有相等则添加到交集中,直到循环结束。 但是这样做,会增加很多的不必要的遍历:比如说,当一个字符串中有多个相同的元素时,该元素会被遍历多次。 因此,在求解时,我们可以先将字符串转换为set集合类型。集合中存储的元素没有顺序,且互异(即元素不可重复)。 算例 求字符串m“abcdaaa” 与 字符串n“bcddses”是否存在交集 首先将字符串转换为set类型: m = set(m) n

lovetaozibaby的博客 1万+

奇安信算法岗笔试复盘:从KMP到安全场景的考点全解析

数据结构与算法是技术面试的基石,而安全厂商的算法岗更看重将算法落地到真实业务的能力。字符串匹配算法如KMP,广泛应用于恶意签名匹配与流量检测;路径遍历防护则考验对输入验证与规范化处理的工程理解;规则引擎中的Rete算法,则是海量规则匹配性能优化的关键。与此同时,机器学习基础(如聚类、变分推断、强化学习)与经典优化算法(如模拟退火、PID)的概念辨析,也是笔试中的高频区分点。本文结合奇安信算法方向笔试真题,梳理题型结构、核心考点与备考策略,帮助候选人理解安全场景下算法能力的考察逻辑,从通用算法基本功到业务实战

weixin_33858336的博客 357

编写用户帮助/操作手册指南

一个新系统,需要写用户操作手册,该从何下笔?本篇是一篇教你编写用户帮助/操作手册的指南~

pytester的博客 3万+

2024秋招淘天算法岗笔试复盘:KMP、动态规划与机器学习考点精析

从KMP算法的next数组计算到动态规划的状态转移,再到机器学习中的评估指标,这些基础技术概念看似独立,却共同构成了算法岗位笔试的核心考点。理解它们的原理不仅能解决字符串匹配、最长递增子序列、模型过拟合等典型问题,更能帮助候选人在大规模数据场景下做出正确的复杂度优化和模型选择。在互联网大厂的技术招聘中,这些知识被灵活地应用于区间覆盖、带权序列优化、Transformer复杂度分析等真实题目中。本文基于2024年秋招阿里淘天算法岗第二批笔试的实战经历,系统复盘了笔试中的选择题与编程题,并给出了时间管理与备考建

weixin_34185512的博客 312

从拆箱到跑通:Intel RealSense D435i开箱实测+ROS驱动配置全流程

本文详细记录了Intel RealSense D435i深度相机的开箱体验,并提供了在Ubuntu 22.04与ROS2 Humble环境下,从安装librealsense2 SDK到配置ROS2驱动的完整流程。重点解决了驱动安装、数据流发布、点云对齐以及IMU数据融合等关键步骤,帮助研究者和开发者快速实现D435i与机器人系统的集成。

weixin_29168393的博客 305

ollama服务暴露公网?三步搞定Nginx反向代理配置(避坑指南)

本文详细介绍了如何通过Nginx反向代理安全地将Ollama服务暴露到公网,避免直接修改OLLAMA_HOST带来的安全隐患。文章提供了从SSL证书部署到高级安全加固的全流程实战指南,包括IP白名单、基础认证、速率限制等企业级安全措施,帮助用户实现安全可靠的外部访问。

wood5的博客 178

淘天算法岗笔试复盘:核心考点与实战策略

在算法岗求职中,扎实的数据结构与经典算法是基石。KMP算法通过next数组避免重复匹配,将字符串匹配复杂度优化至线性,是搜索引擎与文本处理的核心技术;动态规划则强调状态定义与边界处理,在路径优化、资源分配等场景中应用广泛。贪心、堆排序与快速幂则体现了对资源最优利用的思维,Top-K问题和快速幂运算在真实业务中有着直接对应。机器学习理论同样不可忽视,损失函数设计与优化方法选择彰显算法工程师的基本功。本文从这些基础概念与技术原理出发,结合淘天算法岗第二批笔试的真实考点,分析高频算法背后的逻辑与工程价值,并给出备

weixin_33796177的博客 426

unitree-G1外接 USB 麦克风完整配置指南

首先,将type-c麦克风插入G1机器人的USB口后,记录下USB麦克风的卡号(card)和设备号(device),通常显示为 card 1: Device [USB Audio Device]

m0_47999117的博客 600

golang面试

每第61次,会直接从全局队列取,避免goroutine饥饿。

诸君拔剑吧. 2048

AutoSAR系列讲解(入门篇)4.6-BSW的Watchdog功能

BSW的看门狗功能

雪云飞星的博客 1万+

高空抛物监控系统:基于YOLOv8的轨迹追踪与可视化系统

本文详细介绍了一种基于YOLOv8深度学习模型的高空抛物监控系统,该系统能够实时检测并追踪高层建筑抛掷物的运动轨迹。文章包含完整的系统设计思路、算法实现细节、数据集构建方法以及基于PyQt5的可视化界面开发过程。我们提供了完整的Python实现代码,并讨论了系统的性能优化策略和实际部署考量。此外,我们还推荐了几个公开可用的高空抛物数据集,并详细分析了系统的应用前景和技术挑战。

YOLO 446

Makefile学习笔记4

参考文件是: 跟我一起写 Makefile     作者:陈皓 1、dir $(dir) 名称:取目录函数——dir。 功能:从文件名序列中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分。如果没有反斜杠,那么返回“./”。 返回:返回文件名序列的目录部分。 示例: $(dir src/foo.c hacks)返回值是“src/ ./”。 2、notdir $(

cherishTM的博客 431

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

前缀函数,AC自动机

前缀函数,AC自动机 洛谷p2375 前缀函数的应用。 题目大意:我们都知道前缀函数,但现在要求求出一个更强大num数组一一对于字符串S的前i个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]。 ​ 其实只要找出最长符合要求前缀即可,更短的一定是最长符合要求前缀的前缀,推前缀函数时求一个“前缀”和就好(即累加到最长前缀上)。如何求最长不重合既是前缀又是后缀的串呢?前缀函数求的会包含重合的,想一想最开始重合那个过程,在i-1的位置如i=7,在i=6的位

Flyzz的博客 567

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

前缀函数及kmp算法

1、字符串基础 1.1字符集 一个字符集是一个建立了全序关系的集合,也就是说中的任意两个不两只的元素和都可以比较大小,要么,要么。字符集中的元素称为字符。 1.2字符串 一个字符串S是将n个字符顺次排列形成的序列,n称为S的长度,表示为。S的第i个字符表示为S[i]。 1.3子串 字符串S的子串S[i..j],,表示S串中从i到j这一段,也就是顺次排列S[i], S[i+1],...,S[j]形成的字符串。 1.4子序列 字符串S的子序列是从S中将若干元素提取出来并不改变相对位置形成...

多看多听多总结 843

【我的板子】前缀函数

文章目录一、点击查看参考及定义二、计算前缀函数的朴素算法三、前缀函数的第一个优化四、第二个优化 一、点击查看参考及定义 给定一个长度为 n 的字符串 s,其前缀函数被定义为一个长度为 n 的数组 pi 。 主要就是来求一个字符串从第一个字符开始的每一个子串的前缀后缀相等的最长长度。 比如:求abcab的前缀函数求得就是 a的前缀后缀最长的长度:1 ab的前缀后缀最长的长度:0 abc的前缀后缀最长的长度:0 abca的前缀后缀最长的长度:1 abcab的前缀后缀最长的长度:2 所以要求一个字符串的前缀后缀

yxmbbd的博客 946

全网讲解最详细的前缀函数与KMP算法(翻译自 CP-Algorithms,非本人原创,文章中有直达链接)

前缀函数与KMP算法

m0_53387935的博客 1372

140.KMP算法

KMP算法是一种用于在字符串中查找子串的高效算法。它的核心思想是利用之前已经部分匹配的结果来减少不必要的比较,从而提高查找速度。

weixin_63779802的博客 704

[算法] 前缀函数与KMP算法

但是这意味着最后一个块同倒数第二个块相等,并且倒数第二个块同倒数第三个块相等,等等。作为其结果,所有块都是相等的,因此我们可以将字符串。整除),也即其所表示的后缀将部分的覆盖第一个块。现在考虑字符串的第二个块。值得注意的是,我们也可以重新计算在头部添加一个字符,或者从尾或者头移除一个字符时的本质不同子串数目。,我们希望找到其最短的「压缩」表示,也即我们希望寻找一个最短的字符串。就是答案,否则不存在一个有效的压缩,故答案为。更小的压缩表示,那么前缀函数的最后一个值。最长的相等的真前缀与真后缀的长度。

Edward The Bunny 的博客 597

kmp算法

πik0⋯imax​k∣s0⋯k−1==si−k−1⋯i简单来说就是最长的相等的真前缀与真后缀的长度。

思维缜密的博客 538

前缀函数与KMP

1、字符串相关定义1、字符串相关定义2、前缀函数3、计算前缀函数如下是字符串下标以0开始时的代码思路:如下是字符串下标以0开始时的代码思路:4、KMP除了构造新串来求解字符串匹配,如下还有kmp的另一种写法:5、拓展6、前缀函数构造自动机。

吴旭亮 907
上一篇: 「字符串」字符串哈希|RK匹配:前缀哈希|滚动哈希 / LeetCode 28(C++)
下一篇: 「数组」希尔排序 / 区间增量优化(C++)
Daking-
博客等级 码龄3年 912粉丝 70原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值