kmp算法next计算方法

合集下载

kmp算法 公式

kmp算法 公式

KMP算法是一种字符串匹配算法,用于在一个主串中查找一个模式串的出现位置。

它的核心思想是利用已经匹配过的部分信息,尽量减少不必要的比较。

KMP算法的公式如下:1. 预处理模式串,得到next数组:-初始化next数组,next[0] = -1,next[1] = 0;-从第2个字符开始,依次计算next[i]的值:-如果模式串的前缀和后缀匹配,即pattern[j] == pattern[i-1],则next[i] = j + 1;-如果模式串的前缀和后缀不匹配,即pattern[j] != pattern[i-1],则需要回溯到前一个可能的匹配位置,即j = next[j],直到找到一个匹配位置或者回溯到起始位置;-如果回溯到起始位置仍然没有找到匹配位置,则next[i] = 0。

2. 在主串中查找模式串:-初始化主串指针i = 0,模式串指针j = 0;-依次比较主串和模式串的字符:-如果主串和模式串的字符匹配,即text[i] == pattern[j],则继续比较下一个字符;-如果主串和模式串的字符不匹配,即text[i] != pattern[j],则需要根据next数组回溯模式串的指针j,即j = next[j],直到找到一个匹配位置或者回溯到起始位置;-如果回溯到起始位置仍然没有找到匹配位置,则主串指针i和模式串指针j都向后移动一位,继续比较下一个字符;-如果模式串指针j移动到模式串的末尾,则表示找到了一个匹配位置,返回匹配位置的起始索引;-如果主串指针i移动到主串的末尾,则表示没有找到匹配位置,返回-1。

KMP算法通过预处理模式串得到next数组,利用next数组的信息在匹配过程中尽量减少不必要的比较,提高了匹配效率。

KMP算法以及优化(代码分析以及求解next数组和nextval数组)

KMP算法以及优化(代码分析以及求解next数组和nextval数组)

KMP算法以及优化(代码分析以及求解next数组和nextval数组)KMP算法以及优化(代码分析以及求解next数组和nextval数组)来了,数据结构及算法的内容来了,这才是我们的专攻,前⾯写的都是开胃⼩菜,本篇⽂章,侧重考研408⽅向,所以保证了你只要看懂了,题⼀定会做,难道这样思想还会不会么?如果只想看next数组以及nextval数组的求解可以直接跳到相应部分,思想总结的很⼲~~⽹上的next数组版本解惑先总结⼀下,⼀般KMP算法的next数组结果有两个版本,我们需要知道为什么会存在这种问题,其实就是前缀和后缀没有匹配的时候next数组为0还是为1,两个版本当然都是对的了,如果next数组为0是的版本,那么对于前缀和后缀的最⼤匹配长度只需要值+1就跟next数组是1的版本⼀样了,其实是因为他们的源代码不⼀样,或者对于模式串的第⼀个下标理解为0或者1,总之这个问题不⽤纠结,懂原理就⾏~~那么此处,我们假定前缀和后缀的最⼤匹配长度为0时,next数组值为1的版本,考研⼀般都是⽤这个版本(如果为0版本,所有的内容-1即可,如你算出next[5]=6,那么-1版本的next[5]就为5,反之亦然)~~其实上⾯的话总结就是⼀句话next[1]=0,j(模式串)数组的第⼀位下标为1,同时,前缀和后缀的最⼤匹配长度+1即为next数组的值,j所代表的的是序号的意思408反⼈类,⼀般数组第⼀位下标为1,关于书本上前⾯链表的学习⼤家就应该有⽬共睹了,书本上好多数组的第⼀位下标为了⽅便我们理解下标为1,想法这样我们更不好理解了,很反⼈类,所以这⾥给出next[1]=0,前缀和后缀的最⼤匹配长度+1的版本讲解前⾔以及问题引出我们先要知道,KMP算法是⽤于字符串匹配的~~例如:⼀个主串"abababcdef"我们想要知道在其中是否包括⼀个模式串"ababc"初代的解决⽅法是,朴素模式匹配算法,也就是我们主串和模式串对⽐,不同主串就往前移⼀位,从下⼀位开始再和模式串对⽐,每次只移动⼀位,这样会很慢,所以就有三位⼤神⼀起搞了个算法,也就是我们现在所称的KMP算法~~代码以及理解源码这⾥给出~~int Index_KMP(SString S,SString T,intt next[]){int i = 1,j = 1;//数组第⼀位下标为1while (i <= S.length && j <= T.length){if (j == 0 || S.ch[i] == T.ch[j]){//数组第⼀位下标为1,0的意思为数组第⼀位的前⾯,此时++1,则指向数组的第⼀位元素++i;++j; //继续⽐较后继字符}elsej = next[j]; //模式串向右移动到第⼏个下标,序号(第⼀位从1开始)}if (j > T.length)return i - T.length; //匹配成功elsereturn 0;}接下来就可以跟我来理解这个代码~~还不会做动图,这⾥就⼿画了~~以上是⼀般情况,那么如何理解j=next[1]=0的时候呢?是的,这就是代码的思路,那么这时我们就知道,核⼼就是要求next数组各个的值,对吧,⼀般也就是考我们next数组的值为多少~~next数组的求解这⾥先需要给出概念,串的前缀以及串的后缀~~串的前缀:包含第⼀个字符,且不包含最后⼀个字符的⼦串串的后缀:包含最后⼀个字符,且不包含第⼀个字符的⼦串当第j个字符匹配失败,由前1~j-1个字符组成的串记为S,则:next[j]=S的最长相等前后缀长度+1与此同时,next[1]=0如,模式串"ababaa"序号J123456模式串a b a b a anext[j]0当第六个字符串匹配失败,那么我们需要在前5个字符组成的串S"ababa"中找最长相等的前后缀长度为多少再+1~~如串S的前缀可以为:"a","ab","aba","abab",前缀只不包括最后⼀位都可串S的后缀可以为:"a","ba","aba","baba",后缀只不包括第⼀位都可所以这⾥最⼤匹配串就是"aba"长度为3,那么我们+1,取4序号J123456模式串a b a b a anext[j]04再⽐如,当第⼆个字符串匹配失败,由前1个字符组成的串S"a"中,我们知道前缀应当没有,后缀应当没有,所以最⼤匹配串应该为0,那么+1就是取1~~其实这⾥我们就能知道⼀个规律了,next[1]⼀定为0(源码所造成),next[2]⼀定为1(必定没有最⼤匹配串造成)~~序号J123456模式串a b a b a anext[j]014再再⽐如,第三个字符串匹配失败,由前两个字符组成的串S"ab"中找最长相等的前后缀长度,之后再+1~~前缀:"a"后缀:"b"所以所以这⾥最⼤匹配串也是没有的长度为0,那么我们+1,取1序号J123456模式串a b a b a anext[j]0114接下来你可以⾃⼰练练4和5的情况~~next[j]011234是不是很简单呢?⾄此,next数组的求法以及kmp代码的理解就ok了~~那么接下来,在了解以上之后,我们想⼀想KMP算法存在的问题~~KMP算法存在的问题如下主串:"abcababaa"模式串:"ababaa"例如这个问题我们很容易能求出next数组序号J123456模式串a b a b a anext[j]011234此时我们是第三个字符串匹配失败,所以我们的next[3]=1,也就是下次就是第⼀个字符"a"和主串中第三个字符"c"对⽐,可是我们刚开始的时候就已经知道模式串的第三个字符"a"和"c"不匹配,那么这⾥不就多了⼀步⽆意义的匹配了么?所以我们就会有kmp算法的⼀个优化了~~KMP算法的优化我们知道,模式串第三个字符"a"不和主串第三个字符"c"不匹配,next数组需要我们的next[3]=1,也就是下次就是第⼀个字符"a"和主串中第三个字符"c"对⽐,之后就是模式串第⼀个字符"a"不和"c"匹配,就是需要变为next[1]=0,那么我们要省去步骤,不就可以直接让next[3]=0么?序号J12345模式串a b a b anext[j]01123nextval[j]00那么怎么省去多余的步骤呢?这就是nextval数组的求法~~nextval的求法以及代码理解先贴出代码for (int j = 2;j <= T.length;j++){if (T.ch[next[j]] == T.ch[j])nextval[j] = nextval[next[j]];elsenextval[j] = next[j];}如序号J123456模式串a b a b a anext[j]011234nextval[j]0⾸先,第⼀次for循环,j=2,当前序号b的next[2]为1,即第⼀个序号所指向的字符a,a!=当前序号b,所以nextval[2]保持不变等于next[2]=1序号J123456模式串a b a b a anext[j]011234nextval[j]01第⼆次for循环,j=3,当前序号a的next[3]为1,即第⼀个序号所指向的字符a,a=当前序号a,所以nextval[3]等于nextval[1]=0序号J123456模式串a b a b a anext[j]011234nextval[j]010第三次for循环,j=4,当前序号b的next[4]为2,即第⼆个序号所指向的字符b,b=当前序号b,所以nextval[4]等于nextval[2]=1序号J123456模式串a b a b a anext[j]011234nextval[j]0101就是这样,你可以练练5和6,这⾥直接给出~~序号J123456模式串a b a b a anext[j]011234nextval[j]010104⾄此nextval数组的求法你也应该会了,那么考研要是考了,那么是不是就等于送分给你呢?⼩练习那么你试着来求⼀下这个模式串的next和nextval数组吧~~next[j]nextval[j]⼩练习的答案序号j12345模式串a a a a b next[j]01234 nextval[j]00004。

kmp算法next计算方法

kmp算法next计算方法

kmp算法next计算方法KMP算法是一种字符串匹配算法,它的核心在于利用已经部分匹配的信息来减少匹配的次数,从而提高匹配的效率。

而KMP算法中的next数组计算方法则是KMP算法的关键之一,它是用来存储模式串中前缀和后缀的最长公共元素的长度。

接下来我们将详细介绍KMP算法中next数组的计算方法。

首先,我们需要了解next数组的含义。

next数组是针对模式串而言的,它的长度与模式串的长度相同。

next数组中的每个元素表示在当前位置之前的字符串中,有多大长度的相同前缀和后缀。

例如,对于模式串"ababaca",其next数组为[-1, 0, 0, 1, 2, 3, 0],表示在每个位置之前的字符串中,有多大长度的相同前缀和后缀。

接下来,我们来介绍如何计算next数组。

假设模式串的长度为m,我们需要计算出next[1]到next[m-1]的值。

首先,我们可以将next[0]的值设为-1,这是因为next数组中的值表示的是前缀和后缀的最长公共元素的长度,而在第一个位置之前并没有字符串,因此其值为-1。

接着,我们从第二个位置开始计算next数组的值。

假设我们已经知道next[i-1]的值,现在我们来计算next[i]的值。

如果模式串的第i个字符和第next[i-1]+1个字符相等,那么next[i]的值就是next[i-1]+1;如果不相等,我们就需要继续往前找前缀和后缀的最长公共元素的长度,直到找到相等的情况或者完全没有相等的情况。

具体的计算方法可以用如下的伪代码表示:```python。

def getNextArray(s):n = len(s)。

next = [-1] n。

k = -1。

j = 0。

while j < n 1:if k == -1 or s[j] == s[k]:k += 1。

j += 1。

next[j] = k。

else:k = next[k]return next。

C#版KMP算法

C#版KMP算法

C#版KMP算法/// <summary>/// 求⼀个字符串的回溯函数。

/// 约定序列下标从0开始。

/// 回溯函数是整数集[0,n-1]到N的映射,n为字符串的长度。

/// 回溯函数的定义:/// 设存在⾮空序列L,i为其合法下标;/// L[i]的前置序列集为:{空集,L中所有以i-1为最后⼀个元素下标的⼦序列}/// L的前置序列集为:{空集,L中所有以0为第⼀个元素下标的⼦序列}/// 下标i的回溯函数值的定义为:/// 如果i=0,回溯函数值为-1/// 否则i的回溯函数值为i的前置序列集和L的前置序列集中相等元素的最⼤长度,但是相等的两个元素不能是L中的同⼀个⼦串,例如[0-i,1]~[i-1,0]reversed/// 换句话说是,设集合V={x,x属于i的前置序列集,并且x属于L的前置序列集,并且x的长度⼩于i},回溯函数值为max(V).length/// 当i=0时并不存在这样的⼀个x,所以约定此时的回溯函数值为-1/// 回溯函数的意义:/// 如果⼦串中标号为j的字符同主串失配,那么将⼦串回溯到next[j]继续与主串匹配,如果next[j]=-1,则主串的匹配点后移⼀位,同⼦串的第⼀个元素开始匹配。

/// 同⼀般的模式匹配算法相⽐,kmp通过回溯函数在失配的情况下跳过了若⼲轮匹配(向右滑动距离可能⼤于1)/// kmp算法保证跳过去的这些轮匹配⼀定是失配的,这⼀点可以证明/// </summary>/// <param name="pattern">模式串,上⾯的注释⾥将其称为⼦串</param>/// <returns>回溯函数是kmp算法的核⼼,本函数依照其定义求出回溯函数,KMP函数依照其意义使⽤回溯函数。

</returns>public static int[] Next(string pattern){int[] next = new int[pattern.Length];next[0] = -1;if (pattern.Length < 2) //如果只有1个元素不⽤kmp效率会好⼀些{return next;}next[1] = 0; //第⼆个元素的回溯函数值必然是0,可以证明://1的前置序列集为{空集,L[0]},L[0]的长度不⼩于1,所以淘汰,空集的长度为0,故回溯函数值为0int i = 2; //正被计算next值的字符的索引int j = 0; //计算next值所需要的中间变量,每⼀轮迭代初始时j总为next[i-1]while (i < pattern.Length) //很明显当i==pattern.Length时所有字符的next值都已计算完毕,任务已经完成{ //状态点if (pattern[i - 1] == pattern[j]) //⾸先必须记住在本函数实现中,迭代计算next值是从第三个元素开始的{ //如果L[i-1]等于L[j],那么next[i] = j + 1next[i++] = ++j;}else{ //如果不相等则检查next[i]的下⼀个可能值----next[j]j = next[j];if (j == -1) //如果j == -1则表⽰next[i]的值是1{ //可以把这⼀部分提取出来与外层判断合并//书上的kmp代码很难理解的⼀个原因就是已经被优化,从⽽遮蔽了其实际逻辑next[i++] = ++j;}}}return next;}/// <summary>/// KMP函数同普通的模式匹配函数的差别在于使⽤了next函数来使模式串⼀次向右滑动多位称为可能/// next函数的本质是提取重复的计算/// </summary>/// <param name="source">主串</param>/// <param name="pattern">⽤于查找主串中⼀个位置的模式串</param>/// <returns>-1表⽰没有匹配,否则返回匹配的标号</returns>public static int ExecuteKMP(string source, string pattern){int[] next = Next(pattern);int i = 0; //主串指针int j = 0; //模式串指针//如果⼦串没有匹配完毕并且主串没有搜索完成while (j < pattern.Length && i < source.Length){if (source[i] == pattern[j]) //i和j的逻辑意义体现于此,⽤于指⽰本轮迭代中要判断是否相等的主串字符和模式串字符 {i++;j++;}else{j = next[j]; //依照指⽰迭代回溯if (j == -1) //回溯有情况,这是第⼆种{i++;j++;}}}//如果j==pattern.Length则表⽰循环的退出是由于⼦串已经匹配完毕⽽不是主串⽤尽return j < pattern.Length ? -1 : i - j;}ps:个⼈认为kmp算法是⼀个很难的算法,证明它得需要2页纸。

KMP算法:next和nextval值计算

KMP算法:next和nextval值计算

KMP算法:next和nextval值计算
KMP算法的next和nextval值计算
先看看next数据值的求解⽅法
例:下标从1开始(若题中给定下标为0开始,把所有值-1即可)
next数组的求解⽅法:根据前⼀个字符next,⼀直循环找到第⼀次匹配成功的下标,并把next=1;如果当前字符与下标1字符都不相同,next 值就为1(初始下标值)
第⼀位为0,第⼆位为1,
第三位:把前⼀个模式串字符b与下标next值所对应的字符⽐较,b 和a不同,next为1(初始下标值)
第四位:前⼀个,c c和a不同,next为1
第五位:a和a相同(下标为1)1+1=2
第六位:b和b相同(下标为2)2+1=3
第七位:a和c不同(下标为3),继续找,c下标为1,a和a相同(下标为1) 1+1=2
nextval数组求解⽅法:根据next数组的值作为下标找到第⼀个不同的字符,把它的下标作为nextval的值;否则继续循环⽐较,直到与第⼀个字符也相同,此时,nextval值为0
第⼀位为0,第⼆位为1,
第三位:(当前下标字符)c与a(next值1作为下标的字符进⾏⽐较),若不同则为初始下标值1
第四位: a和a相同(第⼀个字符),nextval值为0
第五位:b和b(下标为2),相同,继续⽐较,b的next为1,b和下标为1的⽐,即b和a⽐,不同,则nextval值为1
第六位:a和c(下标为3),不同,nextval为下标的值 3
第七位:a和b(下标为2),不同,nextval为下标的值 2
注:如果下标从0开始,只需把所有的next和nextval值-1就是。

KMP算法详解

KMP算法详解

KMP算法详解KMP 算法详解KMP 算法是⼀个⼗分⾼效的字符串查找算法,⽬的是在⼀个字符串 s 中,查询 s 是否包含⼦字符串 p,若包含,则返回 p 在 s 中起点的下标。

KMP 算法全称为 Knuth-Morris-Pratt 算法,由 Knuth 和 Pratt 在1974年构思,同年 Morris 也独⽴地设计出该算法,最终由三⼈于1977年联合发表。

举⼀个简单的例⼦,在字符串 s = ababcabababca 中查找⼦字符串 p = abababca,如果暴⼒查找,我们会遍历 s 中的每⼀个字符,若 s[i] = p[0],则向后查询p.length() 位是否都相等。

这种朴素的暴⼒的算法复杂度为O(m×n),其中m和n分别是 p 和 s 的长度。

KMP 算法可以⽅便地简化这⼀查询的时间复杂度,达到O(m+n)。

1. PMT 序列PMT 序列是 KMP 算法的核⼼,即 Partial Match Table(部分匹配表)。

举个例⼦:char a b a b a b c aindex01234567PMT00123401PMT 的值是字符串的前缀集合与后缀集合的交集中最长元素的长度。

PMT[0] = 0: 字符串 a 既没有前缀,也没有后缀;PMT[1] = 0: 字符串 ab 前缀集合为 {a},后缀集合为 {b},没有交集;PMT[2] = 1: 字符串 aba 前缀集合为 {a, ab},后缀集合为 {ba, a},交集为 {a},交集元素的最长长度为1;PMT[3] = 2: 字符串 abab 前缀集合为 {a, ab, aba},后缀集合为 {bab, ab, b},交集为 {ab},交集元素的最长长度为2;…… 以此类推。

2. 算法主体现在我们已经知道了 PMT 序列的含义,那么假设在 PMT 序列已经给定的情况下,如何加速字符串匹配算法?tar 存储 s 的下标,从 0 开始,若 tar > s.length() - 1,代表匹配失败;pos 存储 p 的下标,从 0 开始,若 s[tar] != p[pos],则 pos ⾛到下⼀个可能匹配的位置。

扩展KMP算法

扩展KMP算法

如何求解next[]数组 如何求解next[]数组 next[]
还剩下一个问题:next[]这个辅助数组怎 么计算?复杂度是多少? 我们发现计算next实际上以 为母串、T 实际上以T为母串 实际上以 为母串、 为子串的一个特殊“扩展的KMP”。用上 为子串的一个特殊“扩展的 ” 文介绍的完全相同的算法计算next即可。 (用next本身计算next,具体可以参考标准 KMP)此不赘述。
Thank you!
容易发现,如果有某个位置i满足 extend[i]=m,那么T就肯定在S中出现过, 并且进一步知道出现首位置是i——而这正 是经典的KMP问题。 因此可见“扩展的KMP问题”是对经典 KMP问题的一个扩充和加难。
例子 S=’aaaaaaaaaabaa a’, T=’aaaaaaaaaaa’。
比如ababab ,next[2] = 4, 2,3匹配0,1 ;然后4,5匹配2,3;相当 于还是匹配0,1 ;所以0,1被重复了3次, 所以只要是能匹配上的,就是在重复前i个 字符 ,能匹配多长,就是重复了多长,直 接用i+next[i]就是最长的长度 。
求解extend数组的模板
void GetExtand(const EleType str[], int strLen, int extand[], const EleType mode[], int modeLen, int next[]) { int i, a, p, j(-1); for (i = 0; i < strLen; ++i, --j) { if (j < 0 || i + next[i - a] >= p) { if (j < 0) j = 0, p = i; while (p < strLen && j < modeLen && str[p] == mode[j]) ++p, ++j; extand[i] = j, a = i; } else extand[i] = next[i - a]; } }

abaabaab的next数组

abaabaab的next数组

abaabaab的next数组是指在字符串abaabaab中,每个前缀的最长相等真前后缀的长度数组。

这个数组在字符串匹配算法中非常重要,它可以帮助我们更快地进行字符串匹配,提高算法的效率。

为了更好地理解abaabaab的next数组,我们首先需要了解字符串匹配算法中的KMP算法。

KMP算法是一种经典的字符串匹配算法,它利用了字符串本身的信息,在匹配过程中尽量减少回溯,以达到提高匹配效率的目的。

在KMP算法中,我们需要先构建出模式串的next数组。

这个next数组其实是一个关于模式串的自身匹配情况的数组,它的定义如下:1. 对于模式串P中的每一个位置i,next[i]的值代表P[0]到P[i]这个子串的最长相等真前后缀的长度。

2. 如果模式串P的长度为n,则next数组的长度也为n。

以abaabaab为例,它的next数组为[0, 0, 1, 1, 2, 3, 4, 5]。

下面我们来详细解释一下这个数组是如何得出的。

1. 我们先来求出每个位置的最长相等真前后缀的长度。

位置0:a,这个位置是一个单字符,自身没有真前后缀,所以长度为0。

位置1:ab,这个位置没有真前后缀,长度为0。

位置2:aba,这个位置的最长相等真前后缀为a,长度为1。

位置3:abaa,这个位置的最长相等真前后缀为a,长度为1。

位置4:abaab,这个位置的最长相等真前后缀为aba,长度为3。

位置5:abaaba,这个位置的最长相等真前后缀为abaab,长度为4。

位置6:abaabaa,这个位置的最长相等真前后缀为abaaba,长度为5。

位置7:abaabaab,这个位置的最长相等真前后缀为abaabaa,长度为5。

经过上面的计算,我们得到了abaabaab的next数组为[0, 0, 1, 1, 2, 3, 4, 5]。

2. 接下来我们来讨论一下如何利用这个next数组来进行字符串匹配。

假设我们现在有一个文本串T和一个模式串P,我们希望在文本串T中找到模式串P的位置。

数据结构教学中KMP算法解析

数据结构教学中KMP算法解析

数据结构教学中KMP算法解析摘要:模式匹配是字符串的基本运算之一,也是数据结构教学中的难点之一。

分析了模式匹配KMP算法以及算法中next函数的含义,给出了next函数的两种实现方法,有助于在教学实践中帮助学生更好地理解该算法。

关键词:数据结构;模式匹配;KMP算法0引言模式匹配(Patten Matching)是许多计算机应用领域的基础问题,在数据结构中模式匹配是字符串的基本运算之一。

字符串模式匹配指的是,找出特定的模式串在一个较长的字符串中出现的位置。

有两个字符串S和T,字符串S称为目标串,字符串T称为模式串,要求找出模式T在S中的首次出现的位置。

一旦模式T在目标S中找到,就称发生一次匹配。

有些应用可能会要求找出所有的匹配位置<sup>[1]</sup>。

例如,目标串S= 'Shanghai',模式串T= 'gha',则匹配结果为4。

模式匹配的典型算法包括朴素匹配算法、KMP算法和BM算法等,其中KMP算法是效率较高且经典的模式匹配算法之一<sup>[2]</sup>。

在数据结构教学中,由于KMP算法较难理解,课堂讲授往往很难取得好的效果。

本文通过对传统的朴素匹配算法与KMP算法的比较,分析next函数的含义以及实现方法,来帮助理解KMP算法。

1朴素匹配算法在朴素匹配算法中,S和T分别为目标串和模式串,变量i和j 为两个静态指针,分别表示S和T中当前正待比较的字符位置。

算法的基本思想是:第1趟匹配:从S的第1个字符(序号为0)起和T的第一个字符比较之,如果相等,则继续逐个比较后续字符(i++;j++),否则开始下一趟匹配。

新的一趟匹配:i的初值为上一趟的初值+1 ,j的初值为1,如果比较结果相等,则继续逐个比较后续字符,否则开始下一趟匹配。

依次类推,直至某一趟匹配中,T的每个字符依次和S中的一个连续的字符序列相等,则称匹配成功,否则称匹配不成功。

详解KMP算法中Next数组的求法

详解KMP算法中Next数组的求法

详解KMP算法中Next数组的求法例如:1 2 3 4 5 6 7 8模式串 a b a a b c a cnext值0 1 1 2 2 3 1 2next数组的求解方法是:第一位的next值为0,第二位的next 值为1,后面求解每一位的next值时,根据前一位进行比较。

首先将前一位与其next值对应的内容进行比较,如果相等,则该位的next 值就是前一位的next值加上1;如果不等,向前继续寻找next值对应的内容来与前一位进行比较,直到找到某个位上内容的next值对应的内容与前一位相等为止,则这个位对应的值加上1即为需求的next值;如果找到第一位都没有找到与前一位相等的内容,那么需求的位上的next值即为1。

看起来很令人费解,利用上面的例子具体运算一遍。

1.前两位必定为0和1。

2.计算第三位的时候,看第二位b的next值,为1,则把b和1对应的a进行比较,不同,则第三位a的next的值为1,因为一直比到最前一位,都没有发生比较相同的现象。

3.计算第四位的时候,看第三位a的next值,为1,则把a和1对应的a进行比较,相同,则第四位a的next的值为第三位a的next 值加上1。

为2。

因为是在第三位实现了其next值对应的值与第三位的值相同。

4.计算第五位的时候,看第四位a的next值,为2,则把a和2对应的b进行比较,不同,则再将b对应的next值1对应的a与第四位的a进行比较,相同,则第五位的next值为第二位b的next值加上1,为2。

因为是在第二位实现了其next值对应的值与第四位的值相同。

5.计算第六位的时候,看第五位b的next值,为2,则把b和2对应的b进行比较,相同,则第六位c的next值为第五位b的next 值加上1,为3,因为是在第五位实现了其next值对应的值与第五位相同。

6.计算第七位的时候,看第六位c的next值,为3,则把c和3对应的a进行比较,不同,则再把第3位a的next值1对应的a与第六位c比较,仍然不同,则第七位的next值为1。

KMP算法中next数组的理解与算法的实现(java语言)

KMP算法中next数组的理解与算法的实现(java语言)

KMP算法中next数组的理解与算法的实现(java语⾔)KMP 算法我们有写好的函数帮我们计算 Next 数组的值和 Nextval 数组的值,但是如果是考试,那就只能⾃⼰来⼿算这两个数组了,这⾥分享⼀下我的计算⽅法吧。

计算前缀 Next[i] 的值:我们令 next[0] = -1 。

从 next[1] 开始,每求⼀个字符的 next 值,就看它前⾯是否有⼀个最长的"字符串"和从第⼀个字符开始的"字符串"相等(需要注意的是,这2个"字符串"不能是同⼀个"字符串")。

如果⼀个都没有,这个字符的 next 值就是0;如果有,就看它有多长,这个字符的next 值就是它的长度。

计算修正后的 Nextval[i] 值:我们令 nextval[0] = -1。

从 nextval[1] 开始,如果某位(字符)与它 next 值指向的位(字符)相同,则该位的 nextval 值就是指向位的 nextval 值(nextval[i] = nextval[ next[i] ]);如果不同,则该位的 nextval 值就是它⾃⼰的 next 值(nextvalue[i] = next[i])。

举个例⼦:计算前缀 Next[i] 的值:next[0] = -1;定值。

next[1] = 0;s[1]前⾯没有重复⼦串。

next[2] = 0;s[2]前⾯没有重复⼦串。

next[3] = 0;s[3]前⾯没有重复⼦串。

next[4] = 1;s[4]前⾯有重复⼦串s[0] = 'a'和s[3] = 'a'。

next[5] = 2;s[5]前⾯有重复⼦串s[01] = 'ab'和s[34] = 'ab'。

next[6] = 3;s[6]前⾯有重复⼦串s[012] = 'abc'和s[345] = 'abc'。

KMP算法的next函数求解和分析过程

KMP算法的next函数求解和分析过程

KMP算法的next函数求解和分析过程转⾃:/wang0606120221/article/details/7402688假设KMP算法中的模式串为P,主串为S,那么该算法中的核⼼是计算出模式串的P的next函数。

KMP算法是在已知的模式串的next函数值的基础上进⾏匹配的。

由于本次只讨论next的求值过程,因此KMP算法的数学推理过程这⾥不再讲解。

从KMP算法的数学推理可知,此next函数只取决与模式匹配串⾃⾝的特点和主串没有任何关系,此函数默认认为next[1]=0,由于next[j]=k表⽰的意义是当模式串和主串的第j个字符不匹配时,那么接下来和主串的第j个字符匹配的字符是模式串的第k个字符。

因此,next[1]=0表⽰当主串的当前字符和模式串的第1个字符不匹配,接下来需要⽤模式串的第0个字符和主串的当前字符匹配,由于模式串下标是从1开始的,所以不可能存在第0个字符,即接下的匹配动作是主串和模式串同时向右移动⼀位,继续模式匹配。

例如:主串:a c a b a a b a a b n a c模式串:a b a a b主串:a c a b a a b a a b n a c模式串: a b a a b主串:a c a b a a b a a b n a c模式串: a b a a b此时,主串和模式串不匹配,⽽next[1]=0,因此,模式串的第0个字符和主串的第2个字符⽐较,⽽模式串没有第0个字符,此时可以把第0个字符理解为空字符,即模式串向右移动⼀位,主串再继续喝模式串匹配,⽽此时的主串的当前字符是第3个字符,整体来看是当主串和模式串的第1个字符不匹配时,主串和模式串同时右移⼀位,然后继续匹配。

接下来讲解⼀般情况下的next函数值求解过程。

设next[j]=k,根据KMP算法的模式串的特点可知,‘p1p2......pk-1’=‘pj-k+1......pj-1’,其中k必须满⾜1<k<j,并且不可能存在k‘>k满⾜上⾯等式。

KMP算法(推导方法及模板)

KMP算法(推导方法及模板)

KMP算法(推导⽅法及模板)介绍克努斯-莫⾥斯-普拉特算法Knuth-Morris-Pratt(简称为KMP算法)可在⼀个主⽂本S内查找⼀个词W的出现位置。

此算法通过运⽤对这个词在不匹配时本⾝就包含⾜够的信息来确定下⼀个匹配将在哪⾥开始的发现,从⽽避免重新检查先前匹配的。

此算法可以在O(n+m)时间数量级上完成串的模式匹配操作,其改进在于:每当⼀趟匹配过程中出现字符⽐较不等时,不需回溯i的指针,⽽是利⽤已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的距离后,继续进⾏⽐较。

kmp的核⼼之处在于next数组,⽽为了⽅便理解,我先介绍KMP的思想KMP匹配当开始匹配时,如果匹配过程中产⽣“失配”时,指针i(原串的下标)不变,指针j(模式串的下标)退回到next[j] 所指⽰的位置上重新进⾏⽐较,并且当指针j退回⾄零时,指针i和指针j需同时加⼀。

即主串的第i个字符和模式的第⼀个字符不等时,应从主串的第i+1个字符起重新进⾏匹配。

简单来说,就是两个串匹配,如果当前字符相等就⽐较两个字符串的下⼀个字符,如果当前匹配不相等时,就让j(待匹配串的下标)回到next[j] 的位置,因为我们已经知道next数组的作⽤是利⽤已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的距离,如ababac与abac⽐较时i=4,j=4时不匹配,则利⽤next数组让j=2继续匹配⽽不⽤重新开始。

(⽬前先不⽤管next数组的值时如何得到的,只要明⽩它的作⽤即可,下⾯回介绍)所以我们可以写出kmp的代码int KMP(char str[],char pat[]){int lenstr=strlen(str);int lenpat=strlen(pat);int i=1,j=1;while(i<=lenstr){if(j==0 || str[i]==pat[j]) //匹配成功继续往后匹配++i,++j;elsej=next[j]; //否则根据next数组继续匹配if(j==lenpat) //说明匹配完成return 1;}return 0;}接下来就是关键的求next数组了next数组⾸先,next数组取决于模式串本⾝⽽与相匹配的主串⽆关,我们可以对其递推得到。

KMP算法详解(超级详细)

KMP算法详解(超级详细)

KMP算法详解(超级详细)KMP算法,全称为Knuth-Morris-Pratt算法,是一种用于字符串匹配的快速算法。

它的核心思想是在匹配过程中,当出现不匹配的情况时,利用已经匹配的字符信息,避免进行重复匹配,从而提高匹配效率。

首先,我们需要了解一个重要的概念,"部分匹配值"(partialmatch table),它指的是字符串的前缀和后缀的最长的共有元素的长度。

例如,在字符串"ABCDABD"中,它的部分匹配值是[0, 0, 0, 0, 1, 2, 0]。

接下来,我们来详细了解KMP算法的实现过程:1.首先,针对模式串(被查找的字符串)进行预处理,得到部分匹配表。

-定义两个指针,i和j,分别指向模式串的开头和当前字符。

-初始化部分匹配表,将第一个元素置为0。

-在循环中,不断地根据当前指针所指向的字符,判断是否匹配。

-若匹配,则将部分匹配表的下一个元素置为当前指针位置的下一个元素的值加1,并同时将当前指针和i都自增1-若不匹配且i>0,则将i更新为部分匹配表的前一个元素的值。

-若不匹配且i=0,则将当前指针自增1-循环结束后,部分匹配表得到构建。

2.匹配过程:-定义两个指针,i和j,分别指向需要匹配的文本和模式串的开头。

-在循环中,不断地根据当前指针所指向的字符,判断是否匹配。

-若匹配,则将两个指针都自增1-若不匹配且j>0,则将j更新为部分匹配表的前一个元素的值。

-若不匹配且j=0,则将当前指针自增1-若模式串的指针j指向了最后一个字符,则说明匹配成功,返回匹配的位置。

-若循环结束仍未找到匹配的位置,则匹配失败。

总结一下,KMP算法可以分为两个步骤:预处理和匹配。

预处理的过程是构建部分匹配表,通过比较前缀和后缀的最长共有元素的长度,将这个长度记录在部分匹配表中。

匹配的过程是根据部分匹配表中的信息,来确定下一步的匹配位置,提高匹配的效率。

通过KMP算法,我们可以有效地解决字符串匹配问题,提高了匹配的效率。

kmp算法next计算方法

kmp算法next计算方法

kmp算法next计算方法KMP算法是一种字符串匹配的经典算法,它的核心在于利用已经部分匹配的信息来减少匹配的次数,从而提高匹配的效率。

而在KMP算法中,next数组的计算是至关重要的一步,它可以帮助我们快速定位到模式串中与文本串不匹配的位置,从而避免不必要的匹配操作。

本文将详细介绍KMP算法中next数组的计算方法。

首先,我们需要了解next数组的含义。

在KMP算法中,next数组用于记录模式串中每个位置的最长公共前缀和最长公共后缀的长度。

具体来说,对于模式串P,其next数组的第i个位置的值next[i]表示P[0]到P[i]这个子串的最长公共前缀和最长公共后缀的长度。

这样,当P[i]与T[j]不匹配时,我们就可以利用next数组中的信息来将模式串P相对于文本串T右移若干位,从而减少匹配的次数。

接下来,我们来介绍next数组的计算方法。

假设模式串P的长度为m,则next数组的长度也为m。

我们首先将next[0]赋值为-1,next[1]赋值为0,这是因为长度为1的子串没有真正的前缀和后缀。

然后,我们使用两个指针i和j来遍历模式串P,其中i从2开始,j从0开始。

在计算next[i]的过程中,我们需要考虑P[i-1]和P[j]两个字符。

如果P[i-1]等于P[j],则说明P[0]到P[i-1]这个子串的最长公共前缀和最长公共后缀的长度是j+1,于是我们将next[i]赋值为j+1,然后将i和j分别加1。

如果P[i-1]不等于P[j],则我们需要将j更新为next[j],然后继续比较P[i-1]和P[j]两个字符,直到找到相等的字符或者j变为0为止。

重复以上步骤,直到计算出整个next数组为止。

这样,我们就得到了模式串P的next数组。

通过计算得到的next数组,我们可以在KMP算法中利用部分匹配的信息来快速移动模式串,从而提高匹配的效率。

因此,next数组的计算是KMP算法中非常重要的一步,它直接影响到算法的性能和效率。

kmp算法中模式串的next数组值

kmp算法中模式串的next数组值

kmp算法中模式串的next数组值
模式串的next数组值是一个与模式串长度相同的数组,用于
指示当匹配失败时应该回退的位置。

计算next数组的方法如下:
1. 首先将next[0]赋值为-1,表示第一个位置没有可回退的位置。

2. 然后,从第二个位置开始,依次计算next[i]的值。

3. 假设已经计算出next[i-1]的值,即前i-1个字符的最长公共
前后缀的长度为next[i-1]。

4. 如果模式串的第i个字符与前i-1个字符的最长公共前后缀
的下一个字符相等,则next[i] = next[i-1] + 1。

5. 如果模式串的第i个字符与前i-1个字符的最长公共前后缀
的下一个字符不相等,则需要不断回退,直到找到一个位置j,使得模式串的前j个字符与前i-1个字符的前j个字符相等。

6. 因此,需要将next[i-1]的值作为起点,依次向左比较,找到
这个位置j。

7. 如果找到了这个位置j,则next[i] = next[j] + 1,表示下一次
匹配失败时应该回退到这个位置。

8. 如果找不到这个位置j,说明前i个字符没有任何公共前后缀,此时next[i] = 0。

根据上述方法,可以依次计算出模式串的next数组的值。

字符串的next数组

字符串的next数组

字符串的next数组
字符串的next数组是一个用于字符串匹配算法中的辅助数组,它记录了一个字符串中每个前缀子串的最长公共前后缀的长度。

在KMP算法中,当模式串中出现匹配失败时,我们可以根据next数组中记录的信息来调整模式串的位置,从而继续进行匹配。

计算next 数组的时间复杂度为O(m),其中m为模式串的长度。

由于next数组的重要性,其计算方法也得到了多种改进,如KMP算法的优化算法——扩展KMP算法。

在实际应用中,字符串的next数组被广泛应用于字符串匹配、文本相似度计算、图像识别等领域。

- 1 -。

求最小正周期的公式

求最小正周期的公式

求最小正周期的公式最小正周期是一个数列中最小的、循环出现的长度,也就是从数列的开头开始连续抽取数列元素所得到的最短循环节。

求最小正周期的公式可以根据数列元素的规律来确定,这里我们来讲述一些数学方法和思路。

一、暴力枚举法暴力枚举法是一种笨拙但是可行的解决方法。

它的思想是从数列的第一个元素开始,逐个尝试每个可能的循环节长度,直到找到最小的正循环节。

具体来说,我们可以按以下步骤进行操作:1. 遍历每个循环节长度i(1<i<n),其中n为数列长度;2. 截取数列中长度为i的子串,记录下来;3. 用两个指针p和q分别指向数列和子串的开头,不断比对它们对应的元素是否一致,直到找到不一致的元素或者子串全部匹配完成;4. 若子串匹配完成,则说明找到了一个循环节,可以比较它的长度是否比已知的循环节长度短,如果是,则更新记录;5. 遍历完所有循环节长度,返回记录的循环节长度。

这个方法虽然不够高效,但是它的正确性是显然的。

时间复杂度为O(n^2)。

二、KMP算法KMP算法(Knuth-Morris-Pratt 算法)也可以用来求解数列的最小正周期。

KMP算法是一种字符串匹配算法,它可以在O(n)时间复杂度下查找一个字符串中是否包含另一个字符串。

使用KMP算法求解最小正周期的方法是:1. 构建next数组:next[i]表示在长度为i的子串中,其前缀和后缀的最长公共部分的长度。

2. 找到最短的循环节:如果一个字符串S具有长度为len的最短循环节,则它一定可以写成头部子串T和循环节R的组合,即S=TR。

此时,我们只需要找到T即可。

3. 在原序列上匹配T:将序列本身作为主串,T作为模式串,使用KMP算法进行匹配。

如果匹配成功,则说明T正是循环节;否则需要根据next数组的信息更新T的位置(即向右移动,直到匹配成功或者T移动到序列末尾)。

这个方法需要先预处理next数组,时间复杂度为O(n)。

在实际应用中,KMP算法常用于字符串匹配和字符串分割等问题。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

kmp算法next计算方法
KMP算法是一种用于字符串匹配的经典算法,它的核心在于通过预处理模式串,得到一个next数组,然后利用这个数组在匹配过程中进行快速跳转,从而提
高匹配效率。

本文将介绍KMP算法中next数组的计算方法。

在KMP算法中,next数组的含义是指在模式串中,以每个字符结尾的子串中,有多大长度的相同前缀后缀。

这个信息非常有用,因为当遇到不匹配的字符时,我们可以利用next数组中的信息,快速地将模式串向后移动,而不是从头开始逐个
字符地比较。

接下来我们来看一下next数组的计算方法。

假设模式串为P,长度为m,我们
要计算出next数组的值。

首先,我们定义next[0]=-1,next[1]=0,这两个是特殊情况。

然后,我们从第二个字符开始,依次计算next[i]的值。

具体的计算方法如下:
1. 如果P[j]等于P[next[j]],则next[j+1]=next[j]+1;
2. 如果P[j]不等于P[next[j]],则需要继续向前寻找,直到找到一个满足P[j]等
于P[next[j]]的位置,或者找到0为止。

这样,我们就可以得到整个next数组的值。

这个过程实际上是在模式串中寻找相同的前缀后缀,然后记录下它们的长度。

这样,在匹配过程中,当遇到不匹配的字符时,我们就可以根据next数组中的值,快速地将模式串向后移动,从而提高
匹配效率。

需要注意的是,由于next数组的计算是基于模式串本身的特性,因此对于不同的模式串,其next数组的值也是不同的。

这就要求我们在实际使用KMP算法时,
需要提前计算好next数组,并将其保存下来,以备匹配过程中使用。

总结一下,KMP算法中next数组的计算方法是一个非常重要的步骤,它直接影响到算法的匹配效率。

通过提前计算好next数组,并在匹配过程中利用它,我们可以大大提高字符串匹配的效率,从而更高效地解决实际问题。

希望本文对KMP算法中next数组的计算方法有所帮助,如果有任何疑问或者建议,欢迎留言讨论。

相关文档
最新文档