【作者Idlear  博客:http://blog.csdn.net/idlear/article/details/19555905】
           这估计是算法连载文章的最后几篇了,马上就要开学了,以后关于算法的更新肯定没有之前那么快了,一方面是因为算法这几篇作为入门也已经算是可以了,我常记得我以前老师说的一句话就是万事开头难,学习计算机就像武侠小说里面练武功一样,一旦打开任督二脉,练成绝世武功就是时间的问题了,另外也是因为我自己的原因也该将精力转向其他的知识了,我的脑子装的还是最原始的系统只能运行一个线程,如果我不手动的去给他切换一下,估计我就要挂在这一棵树上了。接下来任务还是挺繁重的,我想将关于我博客分类里的几个技术的知识都去整理一下,对于之前的设计模式的文章我实在是对不住了,现在看看写的那些感觉就跟翔一样,我会抽时间再重新返厂加工的,对于博客我还是新手,虽然写的并不多,但是却渐渐的喜欢上写博客。也同时谢谢大家的支持,让我们一起加油一起进步吧。
           言归正传字,符串匹配算法就是看字符串a中是否包含字符串b或者a与b是否相等,可能大家最先想到的比较就是for循环嵌套直接一个个的对比即可,这是最普通的匹配算法,也是比较暴力的方式他的学名叫做BF算法,我们这里要说的是KMP算法,KMP算法之所以叫做KMP算法是三个人名字的首字母,他们三个人发现了KMP算法。这里我们定义一下字符串匹配中主串是模板,而子串则是用来验证主串中是否存在的样本。在BF算法中我们可以简单的想象一下,主串跟子串上各有一个指针,比较的过程就是两个指针不停的前进后退。但是要是让我们去看简单的字符串匹配的的问题时,我们根本不需要这样每一次都前进回退的比较,因为有很多值可以很明显的看出来不需要回退,所以如何让算法更加的聪明呢,这里KMP算法就让时间复杂度降到了O(m+n)主串的指针不需要回退,只有子串的指针回退,而子串的指针也不是简单的回到最前面。而是根据一个规则。这里我们需要去好好的研究一下字符串的特点。
我们首先看这样两个字符串 ABADEFG    跟ABD     首先是A与A相比相同,我们去比较B与B相比相同,然后A与D相比不同,这里是不是我们需要退回到B与A相比的位置呢?我们BF算法是这样的,但是我们可以想一下,主串的AB与子串的AB都相同,而这时候我们再去回退去比较主串的B与A是否相等是不是没有必要了,这时候我们应该直接去比较主串的A与子串的A也就是主串的第第三个位置与主串第一个位置,这样主串并没有后退,这是怎么做到的呢,其实我们可以一直分析子串,我们可以想一下如果主串的的每一个都跟子串的第一位不相同那么是不是主串不需要回退就可以完成循环,结果也肯定是没有匹配成功,那么如果主串前n位与子串的前k位相同,那么说明主串的前n-1位与子串的k-1位相同那么我们是不是相当于复制了主串的n-1位,我们可以直接利用子串来处理就知道子串的第k位与主串的第前n-1位是否相等,而更重要的是我们可以得到一个数组,这个数组就是规定我们子串指定的回退位置。其实只要有了这个意识学习kmp就简单多了。而kmp算法的核心就是处理子串计算出回退数组。

          这个例子很好的解释了子串回退数组的生成。大家可以根据他写出算法。可能有很多人觉得kmp算法比较难懂,其实的确是这样的,模式匹配算法中还有很多简单效率可能要比kmp算法还要好的算法,有兴趣的朋友可以查一下像sunday算法,indexof的算法(这个算法就是javaString的indexof方法的实现的算法,测试一下比KMP算法要快了)但是不得不承认KMP算法已成为经典通用的字符串匹配算法。
public class KMP {
	public int kmp(char[] s, char[] ss) {
		int[] next = core(ss);
		int i = 0;
		int j = 0;
		while (i < s.length && j < ss.length) {
			if (j == -1 || s[i] == ss[j]) {
				i++;
				j++;
			} else {
				j = next[j];
			}
		}
		if (j >= ss.length) {
			return i - ss.length+1;
		}
		return -1;
	}

	public int[] core(char[] ss) {

		int i = 0;
		int[] next = new int[ss.length];
		next[0] = -1;
		int j = -1;
		while (i < ss.length-1) {
			if (j == -1 || ss[i] == ss[j]) {
				++i;
				++j;
				if (ss[i] != ss[j]) {
					next[i] = j;
				} else {
					next[i] = next[j];
				}
			} else {
				j = next[j];
			}
		}

		return next;
	}
	public static void main(String[] args) {
		KMP kmp=new KMP();
		System.err.println(kmp.kmp("asdfsasf".toCharArray(), "sasf".toCharArray()));
	}
}

算法起步之kmp算法的更多相关文章

  1. 算法起步之Kruskal算法

    原文:算法起步之Kruskal算法 说完并查集我们接着再来看这个算法,趁热打铁嘛.什么是最小生成树呢,很形象的一个形容就是铺自来水管道,一个村庄有很多的农舍,其实这个村庄我们可以看成一个图,而农舍就是 ...

  2. 算法起步之Prim算法

    原文:算法起步之Prim算法 prim算法是另一种最小生成树算法.他的安全边选择策略跟kruskal略微不同,这点我们可以通过一张图先来了解一下. prim算法的安全边是从与当前生成树相连接的边中选择 ...

  3. 算法起步之Bellman-Ford算法

    原文:算法起步之Bellman-Ford算法 从这篇开始我们开始介绍单源最短路径算法,他是图算法之一,我们前面说的贪心,图的遍历,动态规划都是他的基础,单源最短路径其实说的就是图中节点到节点的最短路径 ...

  4. 算法起步之Dijkstra算法

    原文:算法起步之Dijkstra算法 友情提示:转载请注明出处[作者 idlear    博客:http://blog.csdn.net/idlear/article/details/19687579 ...

  5. 算法笔记之KMP算法

    本文是<算法笔记>KMP算法章节的阅读笔记,文中主要内容来源于<算法笔记>.本文主要介绍了next数组.KMP算法及其应用以及对KMP算法的优化. KMP算法主要用于解决字符串 ...

  6. 问题 1690: 算法4-7:KMP算法中的模式串移动数组

    题目链接:https://www.dotcpp.com/oj/problem1690.html 题目描述 字符串的子串定位称为模式匹配,模式匹配可以有多种方法.简单的算法可以使用两重嵌套循环,时间复杂 ...

  7. 字符串匹配(BF算法和KMP算法及改进KMP算法)

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include<cstring> ...

  8. 算法总结篇---KMP算法

    目录 写在前面 例题 剪花布条 Radio Transmission OKR-Periods of Words 似乎在梦中见过的样子 Censoring 写在前面 仅为自用,不做推广 一起来看猫片吧! ...

  9. 经典KMP算法C++与Java实现代码

    前言: KMP算法是一种字符串匹配算法,由Knuth,Morris和Pratt同时发现(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.比 ...

随机推荐

  1. bytes与str

    Python 3最重要的新特性大概要算是对文本和二进制数据作了更为清晰的区分.文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示.Python 3不会以任意隐式的方式混用str ...

  2. react router 4.0以上的路由应用

    thead>tr>th{padding:8px;line-height:1.4285714;border-top:1px solid #ddd}.table>thead>tr& ...

  3. java将类和函数封装成jar,然后在别的项目中使用这个jar包

    本来想用idea安装的,不过用maven生成后发现jar有20,30M肯定不对,后来还是用eclipse生成了,方便很多 环境: eclipse luna,jdk1.8_112 1.生成jar包,首先 ...

  4. CocoaPods配置步骤

    1.cd  空格 把你的工程文件夹推进去  回车 2.然后输入vi Podfile 3.然后 i  进入插入模式  吧东西粘贴进去 platform :ios, '7.0' pod 'GCJSONKi ...

  5. JavaScript中Object的总结

    基于原型继承,动态对象扩展,闭包,JavaScript已经成为当今世界上最灵活和富有表现力的编程语言之一. 这里有一个很重要的概念需要特别指出:在JavaScript中,包括所有的函数,数组,键值对和 ...

  6. nginx反向代理cas server之1:多个cas server负载均衡配置以及ssl配置

    系统环境采用centOS7 由于cas server不支持session持久化方式的共享,所以请用其他方式代替,例如:组播复制. 为什么不支持session持久化:http://blog.csdn.n ...

  7. ReactJS入门基础

    渲染这俩字可能在很多地方都见过.但可能不太理解是啥意思. 那么首先我们来理解一下渲染. 渲染 我觉得这样理解比较通俗. 我们做一个汽车,开始是没有喷漆的(没有css) 只是些框框架架(HTML标签). ...

  8. JSP手动注入 全

    检测可否注入 http://****.house.sina.com.cn/publics/detail.jsp?id=7674 and 1=1 (正常页面) http://****.house.sin ...

  9. [BZOJ4907]柠檬

    4709: [Jsoi2011]柠檬 Time Limit: 10 Sec  Memory Limit: 128 MB Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳, ...

  10. ZooKeeper数据模型

    ZooKeeper有一个分层的命名空间,类似分布式文件系统.它们唯一的区别就在于在命名空间中每个节点可以有数据关联作为它们的子节点.这就像有一个文件系统允许文件也作为文件目录.节点路径通常表示为规范的 ...