KMP算法 —— next 数组的应用 --- 前缀中最小循环节,最大重复次数

在大神的基础上添加了一点自己的理解:

从图片中可以看出next数组中存的值就是最近一次最近一次循环节的下标。。。

在KMP算法的使用中,首要任务就是获取一个字符串的next数组,所以我们得明白next数组的含义(最好的方法是自己弄个例子,在草稿纸上模拟一下),在这里,通俗一点讲,next[k] 表示,在模式串的 k 个字符失配了,然后下一次匹配从 next[k] 开始(next[k] 中保存的是该失配字符的前一个字符在前面出现过的最近一次失配的字符后面的一个字符的位置;

至于next数组为什么可以用来求重复前缀呢,而且求出来的重复前缀是最小的呢?

next数组的求法:

void getnext(int len){
int i=0,j=-1;
next[0]=-1;
while(i<len){
if(j==-1 || str[i]==str[j]){
i++;j++;
next[i]=j;
}else
j=next[j];
}
}

个人认为,next数组在求解的过程中,用到了KMP的思想,当前失配了,就回溯到上一个next,请见 j=next[j] ,先说个结论,如果到位置 i ,如果有 i%(i-next(i))==0 , 那说明字符串开始循环了,并且循环到 i-1 结束,为什么这样呢?

我们先假设到达位置 i-1 的时候,字符串循环了(到i-1完毕),那么如果到第i个字符的时候,失配了,根据next数组的求法,我们是不是得回溯?

然而回溯的话,由于字符串是循环的了(这个是假定的),next[i] 是不是指向上一个循环节的后面一个字符呢??

是的,上一个循环节的末尾是 next[i]-1 ,然后现在循环节的末尾是 i-1 ,然么循环节的长度是多少呢?

所以,我们有 (i - 1) - ( next[i] - 1 ) = i - next[i]  就是循环节的长度(假设循环成立的条件下),但是我们怎么知道这个循环到底成立吗?

现在我们已经假设了 0————i-1 循环了,那么我们就一共有i 个字符了,如果有 i % ( i - next[i] ) == 0,总的字符数刚好是循环节的倍数,那么说明这个循环是成立的。

注意还有一点,如果 next[i] == 0,即使符合上述等式,这也不是循环的,举个反例

0   1    2   3   4   5

a    b   c   a   b   d

-1   0   0   0   1   2

下标为1,2,3的next值均为0,那么 i%(i-next【i】)=i%i==0,但是这个并不是循环。

解释完毕,然后再来看下,为什么求出来的循环节长度是最小的呢?

因为next数组失配的时候,总是回溯到最近的循环节,所以i-next【i】就是最小的循环节长度

    为什么求出来的循环次数是最多的呢?

    循环节长度是最小的了,那么循环次数肯定是最多的了。

总结一下,如果对于next数组中的 i, 符合 i % ( i - next[i] ) == 0 && next[i] != 0 , 则说明字符串循环,而且

循环节长度为:   i - next[i]

循环次数为:       i / ( i - next[i] )

KMP精讲的更多相关文章

  1. 深入Java核心 Java内存分配原理精讲

    深入Java核心 Java内存分配原理精讲 栈.堆.常量池虽同属Java内存分配时操作的区域,但其适用范围和功用却大不相同.本文将深入Java核心,详细讲解Java内存分配方面的知识. Java内存分 ...

  2. WKWebView API精讲(OC)

    WKWebView API精讲(OC) 前言 鉴于LL同志对笔者说:“能不能写个OC版本的WKWebView的使用教程?”,还积极打赏了30RMB,笔者又怎么好意思拒绝呢,于是才有了下文. 所有看到本 ...

  3. 《VC++ 6简明教程》即VC++ 6.0入门精讲 学习进度及笔记

    VC++6.0入门→精讲 2013.06.09,目前,每一章的“自测题”和“小结”三个板块还没有看(备注:第一章的“实验”已经看完). 2013.06.16 第三章的“实验”.“自测题”.“小结”和“ ...

  4. iOS开发——语法篇OC篇&高级语法精讲二

    Objective高级语法精讲二 Objective-C是基于C语言加入了面向对象特性和消息转发机制的动态语言,这意味着它不仅需要一个编译器,还需要Runtime系统来动态创建类和对象,进行消息发送和 ...

  5. iOS开发——语法篇OC篇&高级语法精讲

    高级语法精讲 一.NSSet.NSMutableSet集合的介绍 1)NSSet.NSMutableSet集合,元素是无序的,不能有重复的值. 2)用实例方法创建一个不可变集合对象 例如: //宏定义 ...

  6. iOS CAShapeLayer精讲

    前言 CAShapeLayer继承自CALayer,因此,可使用CALayer的所有属性.但是,CAShapeLayer需要和贝塞尔曲线配合使用才有意义. 关于UIBezierPath,请阅读文章:i ...

  7. 【C++自我精讲】基础系列二 const

    [C++自我精讲]基础系列二 const 0 前言 分三部分:const用法.const和#define比较.const作用. 1 const用法 const常量:const可以用来定义常量,不可改变 ...

  8. iOS-UI控件精讲之UIView

    道虽迩,不行不至:事虽小,不为不成. 相关阅读 1.iOS-UI控件精讲之UIView(本文) 2.iOS-UI控件精讲之UILabel ...待续 UIView是所有UI控件的基类,在布局的时候通常 ...

  9. 【C++自我精讲】基础系列四 static

    [C++自我精讲]基础系列四 static 0 前言 变量的存储类型:存储类型按变量的生存期划分,分动态存储方式和静态存储方式. 1)动态存储方式的变量,生存期为变量所在的作用域.即程序运行到此变量时 ...

随机推荐

  1. Implement Hash Map Using Primitive Types

    A small coding test that I encountered today. Question Using only primitive types, implement a fixed ...

  2. Triangle 解答

    Question Given a triangle, find the minimum path sum from top to bottom. Each step you may move to a ...

  3. 剑指offer-面试题4.替换空格

    题目:请实现一个函数,把字符串中的每个空格都替换成"%20".例如输入"We are happy." 则输出"We%20are%20happy.&qu ...

  4. 使用lock_sga和pre_page_sga参数保证SGA常驻物理内存 .

    Lock_sga LOCK_SGA locks the entire SGA into physical memory. It is usually advisable to lock the SGA ...

  5. c保存lua函数

    使用下面方式可保存lua任何值,目前只实现fucntion的保存,且无参数.如果需要实现参数,可自己扩展: 可实现下面方式: CFun( lua_fun ) -- okCFun( function() ...

  6. LFS:kernel panic VFS: Unable to mount root fs

    说明: 使用Vm虚拟机构建自己的LFS系统时,系统引导不成功,提示 kernel panic VFS: Unable to mount root fs 参考链接:http://www.52os.net ...

  7. NET基础课--配置文件2

     1. 使用<appSettings>        简单的配置信息,可以直接放入<appSettings>标记中.如: <?xml version="1.0& ...

  8. 【熊猫】POS销售

    select a.itemcode,b.itemname,b.spec,b.unit,b.rprice,sum(a.rqty) rqtyfrom tm_possale_detail a,sys_ite ...

  9. WCF方式调用asmx设置cookie

    以前旧的方式去调用web service, 可以通过CookieContainer去设置cookie,改用WCF方式去调用,则必须配置allowCookies属性为true <system.se ...

  10. RTUILabel+正则表达式

    RTLabel和RegexKitLite都要导入第三方库 使用Regexkitlite库进行正则表达式的解析 1.库是使用MRR,如果在ARC工程里面使用这个类,必须在project->buil ...