KMP算法是字符串匹配的经典算法,简称 看毛片, 理论知识请直接看阮一峰老师的这篇文章,我看完文章之后尝试对算法进行了实现。

一句话总结KMP算法的核心思想:就是跳过已经对比的部分

而KMP算法的核心组成就是部分匹配表 + 回退算法

部分匹配表1.0版本

            function KMPpartMatchTable(str) {
var matchTable = [0];
var prefix = [],
suffix = [];
for(var i = 1; i < str.length; i++) {
prefix = getPrefix(str.substr(0, i + 1))
suffix = getSuffix(str.substr(0, i + 1)) var ret = [0]; //默认设置一个0,防止-Infinity
//对比2个数组,是否有重复的
prefix.forEach(function(n, i) {
for(var j = i; j < suffix.length; j++) {
if(n == suffix[j]) {
ret.push(n.length)
}
}
})
matchTable.push(Math.max.apply(null, ret))
}
//生成前缀数组
function getPrefix(s) {
let ret = []
for(var len = s.length; len > 0; len--) {
if(len == s.length) continue;
ret.push(s.substring(0, len))
}
return ret.reverse();
}
//生成后缀数组
function getSuffix(s) {
let ret = []
for(var len = s.length; len > 0; len--) {
if(len == s.length) continue;
ret.push(s.substring(len, s.length))
}
return ret.reverse();
}
return matchTable
}

这是我第一版写出来的,可以看到2个getPrefix和getSuffix有大部分是重复的代码。方便理解。需要for循环2次字符串,但不利于性能。所以可以将他们进行精简合并为1次

部分匹配表2.0版本

            function KMPpartMatchTable(str) {
var matchTable = [0];
var prefix = [],
suffix = [];
for(var i = 1; i < str.length; i++) {
// prefix = getPrefix(str.substr(0, i + 1))
// suffix = getSuffix(str.substr(0, i + 1))
var s = str.substr(0, i + 1);
for(var len = s.length; len > 0; len--) {
if(len == s.length) continue;
prefix.push(s.substring(0, len)) //前缀数组
suffix.push(s.substring(len, s.length)) //后缀数组
} var ret = [0]; //默认设置一个0,防止-Infinity
//对比2个数组,是否有重复的
prefix.forEach(function(n, i) {
for(var j = i; j < suffix.length; j++) {
if(n == suffix[j]) {
ret.push(n.length)
}
}
})
matchTable.push(Math.max.apply(null, ret))
}
return matchTable
}
            KMPpartMatchTable('ABCDABD')//[0,0,0,0,1,2,0]
 

改进过后,逻辑没那么直观了。但一次字符串for循环就生成出了前缀和后缀数组

回退算法

            function KMP(sourceStr, targetStr) {
var partMatchValue = KMPpartMatchTable(targetStr); //拿到匹配表
var result = false;
for(var i = 0; i < sourceStr.length; i++) {
for(var k = 0; k < targetStr.length; k++) {
if(str.charAt(k) == sourceStr.charAt(i)) {
if(k == targetStr.length - 1) {
result = true;
break;
} else {
i++;
}
} else {
if(k > 0 && partMatchValue[k - 1] > 0) {
k = partMatchValue[k - 1] - 1;
} else {
break;
}
}
}
if(result) {
break;
}
}
return result
} var ss = 'ABCDAB ABCDAB ABCDAABCABCDABDABCDABDDABDBD'
var str = 'ABCDABD'
console.log(KMP(ss, str)) //true

KMP算法用JavaScript实现的更多相关文章

  1. 数据结构与算法JavaScript (五) 串(经典KMP算法)

    KMP算法和BM算法 KMP是前缀匹配和BM后缀匹配的经典算法,看得出来前缀匹配和后缀匹配的区别就仅仅在于比较的顺序不同 前缀匹配是指:模式串和母串的比较从左到右,模式串的移动也是从 左到右 后缀匹配 ...

  2. KMP算法——Javascript实现

    腾讯和阿里的笔试刚过去了,里面有很多题都很值得玩味的.之前Blog积累的很多东西,还要平时看的书,都有很大的帮助.这个深有体会啊! 例如,腾讯有一道算法题是吃香蕉(好邪恶的赶脚..),一次吃一根或者两 ...

  3. javascript实现KMP算法(没啥实用价值,只供学习)

    简单粗暴上代码 KMP的原理我就不讲了,想转过弯儿来不容易,建议大家先学会了怎么推导出next数组规律,然后准备两张纸,大纸上写上一行你要匹配的目标字符串,并分别写出位置编号,小纸上写上一行,也写上位 ...

  4. 理解 KMP 算法

    KMP(The Knuth-Morris-Pratt Algorithm)算法用于字符串匹配,从字符串中找出给定的子字符串.但它并不是很好理解和掌握.而理解它概念中的部分匹配表,是理解 KMP 算法的 ...

  5. 简单有效的kmp算法

    以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...

  6. KMP算法

    KMP算法是字符串模式匹配当中最经典的算法,原来大二学数据结构的有讲,但是当时只是记住了原理,但不知道代码实现,今天终于是完成了KMP的代码实现.原理KMP的原理其实很简单,给定一个字符串和一个模式串 ...

  7. 萌新笔记——用KMP算法与Trie字典树实现屏蔽敏感词(UTF-8编码)

    前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"* ...

  8. KMP算法实现

    链接:http://blog.csdn.net/joylnwang/article/details/6778316 KMP算法是一种很经典的字符串匹配算法,链接中的讲解已经是很明确得了,自己按照其讲解 ...

  9. 扩展KMP算法

    一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...

随机推荐

  1. 理解RESTFul和SOA

    RESTFul:面向资源的架构(roa) RESTFul基于HTTP协议,是一种明确构建在客户端/服务端体系结构上的一种风格, rest是Representational State Transfer ...

  2. iReport(模版) 与Jasper(数据填充)生成pdf文档

    报表模板生成软件:iReport . 润乾.水晶. 一.Jaspersoft iReport Desiginer 5.60 的使用 1.软件jar包的下载地址与配置 百度云盘下载链接:https:// ...

  3. drupal7设置不含www的url跳转到含www的url

    打开drupal的.htaccess文件 找到 If your site can be accessed both with and without the 'www.' prefix 将下面对应的三 ...

  4. create alter rename desc select update delete insert

    conn scott/root;create table student (id number(3), name varchar2(10), sex char(2), sno number(3));a ...

  5. 深入理解net core中的依赖注入、Singleton、Scoped、Transient(一)

    相关文章: 深入理解net core中的依赖注入.Singleton.Scoped.Transient(一) 深入理解net core中的依赖注入.Singleton.Scoped.Transient ...

  6. 在Mac上用bootcamp安装windows,使用Android studio启动模拟器时蓝屏问题的解决方法

    原链接 https://medium.com/@andrea.bresolin/windows-10-on-mac-with-boot-camp-making-intel-haxm-work-with ...

  7. UML 运用于开发过程——总结

    UML -- 统一的图形语言 用例图:需求捕获,测试依据类图:静态系统结构对象图:对象之间的关联构件图:构件之间的关联部署图:构建的物理部署 以上几种图的作用:描述系统结构 顺序图:捕获时间顺序协作图 ...

  8. Docker 监控之 SaaS 解决方案

    过去的一年中,关于 Docker 的话题从未断过,而如今,从尝试 Docker 到最终决定使用 Docker 的转化率依然在逐步升高,关于 Docker 的讨论更是有增无减.另一方面,大家的注意力也渐 ...

  9. Hibernate 集成 Ehcache 开启二级缓存

    一.将 Ehcache.xml 放到 classpath 下 <?xml version="1.0" encoding="UTF-8"?> < ...

  10. Azure 和 Linux

    Azure 正在不断集结各种集成的公有云服务,包括分析.虚拟机.数据库.移动.网络.存储和 Web,因此很适合用于托管解决方案. Azure 提供可缩放的计算平台,允许即用即付,而无需投资购买本地硬件 ...