本文为自己对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. 关于LNMP常见问题和性能方面的个人理解

    简单整理,自己做备忘的,不为其他作任何参考- PHP程序 1.开启慢日志,过滤超时时间为1s的方法,针对性优化,可以通过添加缓存方式解决. 2.过滤access日志,统计哪些请求较多较为频繁,是否合理 ...

  2. location 匹配规则 (NGINX)

    转:https://moonbingbing.gitbooks.io/openresty-best-practices/ngx/nginx_local_pcre.html location 匹配规则 ...

  3. 2019-1-92.4G射频芯片培训资料

    2019-1-92.4G射频芯片培训资料 培训 RF 小书匠  欢迎走进zozo的学习之旅. 2.4G芯片选型 2.4G芯片开发 Q&A 2.4G芯片选型 芯片类型 soc 防盗标签2.4G无 ...

  4. 第一章 Windows编程基础(1~4课)

    第一课:从main到WinMain 第二课:窗口和消息 第三课:MFC编程 第四课:MFC应用程序框架 概括: Win32的两种编程框架:SDK方式.MFC方式 1. SDK方式:使用WinMain入 ...

  5. Python—元组(戴上了枷锁的列表)

    一.概念 元组属于不可变序列,元组是包含多个元素的类型,元素之间用逗号分割.例如:t1=123,456,“hello”元组可以是空的,t2=()元组包含一个元素时:t3=123,元组外侧可以使用括号, ...

  6. NYOJ 35 表达式求值(逆波兰式求值)

    http://acm.nyist.net/JudgeOnline/problemset.php?typeid=4 NYOJ 35 表达式求值(逆波兰式求值) 逆波兰式式也称后缀表达式. 一般的表达式求 ...

  7. Python3.5在Windows7环境下Scrapy库的安装

    Python3.5在Windows7环境下Scrapy库的安装 忙活了一下午,总算是把Scrapy库给装完了,记下来给需要帮助的人 首先安装的环境:Windows7 64位 Python的版本是:3. ...

  8. 感谢信——Alpha版

    作为Thunder团队的leader,当时担任组长,说实话,确实是头脑一热,可后来,在确定选题时,看着大家都有自己的想法,看着大家都那么踊跃,而我因为性格的原因,总是难以做决定,导致选题这件事就开了几 ...

  9. Python基础1 Hello World!

    从今天开始和大家分享一下python最基础的知识,以便帮助初学者快速入门. 最最基础的当然是hello world 了,无论哪门语言都会从它开始... 简单的‘Hello World!’ 1. 直接运 ...

  10. Calculator 2

    github地址:https://github.com/YooRarely/object-oriented.git 新增: 计算类(拥有计算功能) 采用符号优先级计算方法 对符号不匹配的如 -2 ,自 ...