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. html 里面的 role 属性是什么意义和用途

    使用role属性告诉辅助设备(如屏幕阅读器)这个元素所扮演的角色,属于WAI-ARIA. 例如点击的按钮,就是role="button":会让这个元素可点击:本质上是增强语义性,当 ...

  2. Django中间件解析

    一,中间件的概念 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法.在dja ...

  3. 重要BLOG

    Cloud http://www.cnblogs.com/CloudMan6/tag/OpenStack/ 算法基础 http://www.cnblogs.com/ECJTUACM-873284962 ...

  4. Object.defineProperty 与数据绑定的简单实现

    对象是一个属性集合,对象的基本特征是属性名(name)和属性值(value).ES5 增加了属性描述符,包括数据属性描述符(configurable enumerable writable value ...

  5. gitlab的仓库迁移到新的gitlab

    1.下载原有gitlab源码 git clone http://gitlab.**.com/projectName gitlab地址替换成为新gitlab地址 git remote set-url o ...

  6. 手动搭建 redis 集群

    转自http://meia.fun/article/1544161420745 手动搭建 redis 集群 redis 基本命令: 启动 redis 服务:redis-server xxx.conf ...

  7. jquery中的ajax方法

    $.ajax()方法详解 jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Strin ...

  8. HBase Region分裂实现

    分裂策略 不同的分裂策略的实现需要继承RegionSplitPolicy,主要实现两个方法: shouldSplit()表示是否需要分裂 getSplitPoint()得到分裂点rowkey 从 HB ...

  9. .Net Core+Vue.js+ElementUI 实现前后端分离

    .Net Core+Vue.js+ElementUI 实现前后端分离 Tags: Vue 架构 前端采用:Vue.js.Element-UI.axios 后端采用:.Net Core Mvc 本项目是 ...

  10. Oracle诊断工具 - ORA-2730x Troubleshooting Tool

    通常情况下,ORA-27300 ORA-27301 ORA-27302错误的原因是操作系统的系统调用错误或者操作系统配置问题,错误格式:ORA-27300: OS system dependent o ...