本文为自己对KMP的理解。

对KMP很好的介绍可以参考

http://www.cnblogs.com/yjiyjige/p/3263858.html

本文为对这篇文章的提炼和补充。

KMP算法基本思想:要查看字符串S是否包含P,定义 i = 0, j = 0,比较S[i]和P[j],相等就i,j各++,如果失配,照传统的比较,就是j要变成0,i也要回到最初开始的地方+1,重新比较;现在,i不变,j=next[j],然后重复上述:比较S[i]和P[j]。

next数组的定义方式如下(定义来自数据结构第二版4.4.6节,殷人昆主编):

假设字符串P长为m,由p0p1p2...pm-2pm-1构成,next(j)=

-1, 当j==0。

q+1, 当0<=q<j-1 且使得p0p1p2...pq = pj-q-1pj-q...pj-1的最大整数。

0,其他情况。

(next[0] = -1,在当第一位就失配时用到,其值为-1的含义是:i不再是不变,而是+1,同时j 赋值为0,看起来好像j相对于i 成了-1)

可以用递推思想求next[]:

我们用k表示当前next[j]的值,那么就意味着:p0p1p2...pk-1 = pj-k-1pj-k...pj-1,此时我们可以比较pk和pj,如果pk==pj,那么next[j+1]就是k+1,也就是n[j]+1了(之前说了用k表示n[j])。因为根据定义,如果p0p1p2...pk-1 == pj-k-1pj-k...pj-1而且pk==pj,那各自加上一个相等的,自然p0p1p2...pk-1pk == pj-k-1pj-k...pj-1pj依然成立了。

如果pk不等于pj,此时我们琢磨一下next(j)的定义:“使得p0p1p2...pq == pj-q-1pj-q...pj-1的最大整数”,其实就是找到相同的最长公共串,只不过前一个串必须以p0开头,后一个串必须以pj-1结尾。我们已经知道pk不等于pj,所以p0p1p2...pk == pj-q-1pj-q...pj是不可能了,这个问题其实就是:前面都一样,第j位失配。那么我们可以引用KMP本身的思想,将k赋值成next[k],然后重复上述内容:比较pk和pj,不相等就继续将k赋值成next[k],一直到p== p或者 k变成了0或者-1。

因此next数组的代码如下:

public static int[] getNext(String ps) {
char[] p = ps.toCharArray();
int[] next = new int[p.length];
next[0] = -1;
int j = 0;
int k = -1;
while (j < p.length - 1) {
if (k == -1 || p[j] == p[k]) {
next[++j] = ++k;
} else {
k = next[k];
}
}
return next;
}

代码来自引用博文。

有了next[],下面就是匹配了:

public static int KMP(String ts, String ps) {
char[] t = ts.toCharArray();
char[] p = ps.toCharArray();
int i = 0; // 主串的位置
int j = 0; // 模式串的位置
int[] next = getNext(ps);
while (i < t.length && j < p.length) {
if (j == -1 || t[i] == p[j]) { // 当j为-1时,要移动的是i,当然j也要归0
i++;
j++;
} else {
// i不需要回溯了
// i = i - j + 1;
j = next[j]; // j回到指定位置
}
}
if (j == p.length) {
return i - j;
} else {
return -1;
}
}

子字符串substring 问题 - KMP 字符串匹配算法备忘录的更多相关文章

  1. 不可变字符串String与可变字符串StringBuilder、StringBuffer使用详解

    String字符串 char类型只能表示一个字符,而String可以表示字符串,也就是一个字符序列.但String不是基本类型,而是一个定义好的类,是一个引用类型.在Java中,可以将字符串直接量赋给 ...

  2. BM和KMP字符串匹配算法学习

    BM和KMP字符串匹配算法学习 分类: 研究与学习 字符串匹配BM(Boyer-Moore)算法学习心得 http://www.cnblogs.com/a180285/archive/2011/12/ ...

  3. 每周一算法之六——KMP字符串匹配算法

    KMP是一种著名的字符串模式匹配算法,它的名称来自三个发明人的名字.这个算法的一个特点就是,在匹配时,主串的指针不用回溯,整个匹配过程中,只需要对主串扫描一遍就可以了.因此适合对大字符串进行匹配. 搜 ...

  4. 字符串的模式匹配算法——KMP模式匹配算法

    朴素的模式匹配算法(C++) 朴素的模式匹配算法,暴力,容易理解 #include<iostream> using namespace std; int main() { string m ...

  5. KMP字符串模式匹配详解(转)

    来自CSDN     A_B_C_ABC 网友 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算法.可以证明它的时间复杂度 ...

  6. 截取字符串 substring substr slice

    截取字符串   substring 方法用于提取字符串中介于两个指定下标之间的字符  substring(start,end) 开始和结束的位置,从零开始的索引 参数     描述 start     ...

  7. Java 从原字符串中截取一个新的字符串 subString()

    Java 手册 substring public String substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串.该子字符串从指定索引处的字符开始,直 ...

  8. KMP字符串模式匹配详解(zz)

    刚看到位兄弟也贴了份KMP算法说明,但本人觉得说的不是很详细,当初我在看这个算法的时候也看的头晕昏昏的,我贴的这份也是网上找的.且听详细分解: KMP字符串模式匹配详解 来自CSDN     A_B_ ...

  9. LayoutParams 命名的时候,最好用与子控件相关的字符串命名,

    @Override public View initView() { RelativeLayout container = new RelativeLayout(UIUtils.getContext( ...

随机推荐

  1. 在mesh client示例中加入spi_slave接口(without IDE)

    在mesh client示例中加入spi_slave接口(without IDE) 主要是理解cmake构建的过程,然后修改工程中的inlcude路径及c源文件. 1. 解压mesh_sdk unzi ...

  2. Dictionary tabPage使用

    public override bool AccptChange() { //if (oldvalue == null || oldvalue.Count <= 0) //{ // return ...

  3. ZOJ 3644 Kitty's Game(数论+DP)

    Description Kitty is a little cat. She is crazy about a game recently. There arenscenes in the game( ...

  4. Samba共享权限分配

    案例推荐:http://www.cnblogs.com/mchina/archive/2012/12/18/2816717.html 本文不详细介绍全部参数,只介绍完成需求的一些参数. 需求: 1,账 ...

  5. jsp文件中charset和pageEncoding的区别

    jsp文件中charset和pageEncoding的区别:  contentType的charset是指服务器发送给客户端时的内容编码,contentType里的charset=utf-8是指示页面 ...

  6. aria2 on ubuntu

    http://www.5yun.org/9102.html http://jpollo.logdown.com/posts/160847-aria2c-and-yaaw aria2c --enable ...

  7. Swift-map()跟flatMap()区别

    map()方法介绍 map() 是  Array 提供的方法,通过接收一个函数作为传入参数,对数组中每个元素进行函数变换得到新的结果值.这样只需要提供  X->Y 的映射关系,就能将数组  [X ...

  8. 【week4】课堂Scrum站立会议

    项目:连连看游戏 小组名称:天天向上(旁听) 小组成员:张政 张金生 李权 武致远 已完成任务 1.本项目采用c#. 2. 初步界面. 形成一个windows下的游戏界面,每个需要消除的方块是一个bu ...

  9. select模型的原理、优点、缺点

    关于I/O多路复用: I/O多路复用(又被称为“事件驱动”),首先要理解的是,操作系统为你提供了一个功能,当你的某个socket可读或者可写的时候,它可以给你一 个通知.这样当配合非阻塞的socket ...

  10. 通过logger命令记录日志

    通过logger命令记录日志 logger是一个shell命令接口,可以通过该接口使用Syslog的系统日志模块,还可以从命令行直接向系统日志文件写入一行信息. ------------------- ...