KMP算法心得
1 关于next数组
(1)写代码的时候为了避免逻辑混乱, 所以最好还是使得next数组从第零位开始记录, 这样的话, 当本位置发生比较冲突时, 可以直接取本位置存储的数值作为下一次进行比较的位置, 而不需要进行加一或者减一的操作
(2)next数组中记录的是本位置最长公共前后缀的长度,在这里我们需要理解什么是最长公共前后缀:
最长公共前后缀的条件:
** 不包含本位置
** 不能包含本位置之前的全部字符
2 比较的时候,如果第一位就发生了比较冲突, 下一次应该是将源字符串的下一个位置与目标字符串的本位置进行比较,
如果不是第一位比较发生冲突, 那么将会是将源字符串的本位置与目标字符串的新位置进行比较,
这一点之前没有搞清, 所以吃了一点亏
3 如果忘了具体的实施, 了解一下理论即可, 主要是在写代码的过程中上面两点出现了问题, 代码如下:
1 /** 2 * @param {string} s 3 * @return {array} 4 */ 5 const getNext = function (s) { 6 7 let stringArr = s.split("") 8 let nextArr = [] 9 for(let i = 0, length = stringArr.length; i < length; i++) { 10 11 let count = 1 12 while(judge(stringArr, count, i) && count<i) { 13 count++ 14 } 15 16 nextArr[i] = --count 17 } 18 19 return nextArr 20 } 21 22 /** 23 * 24 * @param {array} array 25 * @param {number} n 26 * @param {number} endIndex 27 * @return {boolean} 28 */ 29 const judge = function (array, n, endIndex) { 30 31 let left = 0 32 let right = endIndex-n 33 34 if(endIndex<=1) { 35 return false 36 } 37 38 while(left<n) { 39 if(array[left] !== array[right]) { 40 return false 41 } 42 left++ 43 right++ 44 } 45 return true 46 } 47 48 49 /** 50 * 51 * @param {string} sourceStr 52 * @param {string} targetStr 53 */ 54 const indexof = function (sourceStr, targetStr) { 55 56 let nextArr = getNext(targetStr) 57 58 for(let source = 0, target = 0, length = sourceStr.length; source < length; source++,target++) { 59 60 if(sourceStr.length-source < nextArr.length-target) { 61 return -1 62 }else if(target === nextArr.length-1 && sourceStr[source] === targetStr[target]){ 63 console.log("找到了"+(source-targetStr.length+1)) 64 return source-targetStr.length+1 65 } 66 if(sourceStr.charAt(source) !== targetStr.charAt(target)) { 67 if(target!==0) { 68 source-- 69 } 70 target = nextArr[target]-1 71 } 72 73 } 74 } 75 76 console.log(indexof("aabaac","aa"))