本文为自己对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],一直到pk == pj 或者 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. vue.js学习之 如何在better-scroll加载完成后,自动滚动到最底部

    首先我们需要使用scrollTo这个方法: scrollTo(x, y, time, easing) 参数: {Number} x 横轴坐标(单位 px) {Number} y 纵轴坐标(单位 px) ...

  2. Python中的赋值语法

    Python中复制语法有6种 Basic Form >>>spam = 'spam' Tuple assignment >>>spam, ham = 'spam', ...

  3. 《剑指Offer》题二十一~题三十

    二十一.调整数组顺序使奇数位于偶数前面 题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分. 测试用例: 功能测试:输入数组中的奇 ...

  4. Git 命令基本应用

    两种建立仓库的方法: (1)在本地文件路径下建立仓库:git init (2)在代码托管网站上克隆项目:git clone [url] 查看该分支下的文件情况:git status 添加远程仓库源:g ...

  5. Unity3d学习日记(一)

      闲来无事开始自学unity3d,发现还挺容易入门的,添加资源文件以及用c#编写脚本都很方便.   前面在Unity官方教程上自学了一段时间,跟着教程写了个space_shooter的小游戏,虽然游 ...

  6. 【alpha】Scrum站立会议第3次....10.18

    小组名称:nice! 小组成员:李权 于淼 杨柳 刘芳芳 项目内容:约跑app(约吧--暂定) 1.任务进度 2.燃尽图 功能列表 1.登录注册 2.创建跑步计划 3.筛选跑友 4.加一起跑步的人为好 ...

  7. django 使用json.dumps转换queryset的datatime报错问题解决

    最近在使用django做项目的时候想使用ajax来实现前后台数据的交互,但是在将数据库查询结果转换成json数据时,遇到时间格式的数据转换遇到问题,无法正确的进行转换,具体如下: 转换成json时使用 ...

  8. WebKit 源码分析 -- loader

    原文地址: http://peirenlei.iteye.com/blog/1718569 摘要:本文介绍 WebCore 中 Loader 模块是如何加载资源的,分主资源和派生资源分析 loader ...

  9. zlog使用手册

    zlog使用手册 来源 http://hardysimpson.github.io/zlog/UsersGuide-CN.html Contents Chapter 1  zlog是什么? 1.1   ...

  10. git log 查看提交记录

    git log 查看提交记录 1. git log 查看提交历史记录2. git log --oneline 或者 git log --pretty=oneline 以精简模式显示3. git log ...