KMP
KMP是一种高效的字符串匹配算法,用来在主字符串中查找模式字符串的位置
比如在“hello,world”主串中查找“world”模式串的位置)。
核心思想
在失配时, 将模板字符串失配字符的下标退回到前面相应位置 ,这样就可以跳过大多数的失配步骤。而每次p串移动的步数就是通过查找next[ ]数组确定的。比如 :
父亲字符串 : aabaabaaf
模板字符串 : aabaaf
当模板字符串的f
不匹配父字符串的b
时, 模板字符串中字符f
对应的下标j
就会退回到包括前5个字符组成的子串的最长相同前后缀的长度, 也就是2, 于是退回到下标为2的位置, 从模板字符串的b
字符继续开始和父字符串进行匹配, 至始至终父字符串的匹配下标都未移动哦~
KMP
主要分两步:
- 求next数组
- 匹配字符串
举例 + 详解
![image-20230930021353085](https://weirdo-blog.oss-cn-chengdu.aliyuncs.com/blog/202309300214173.png)
详解 : 都在注释中了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const num = 4; const rows = []; rl.on('line', function(data){ rows.push(data); if (rows.length == num) { const res = []; const n = Number(rows[0]); const m = Number(rows[2]); const p = rows[1]; const s = rows[3]; const next = [0] for(let i = 1, j = 0; i < n; i++) { while(j && p[i] != p[j]) j = next[j - 1]; if(p[i] === p[j])j++; next[i] = j; } for (let i = 0, j = 0; i < m; i++) { while (j && s[i] != p[j]) j = next[j - 1]; if (s[i] == p[j]) j++; if (j == n) { res.push(i - n + 1); j = next[j - 1]; } } console.log(res.join(' ')); rl.close(); } })
|
over
例子2 + 无注释版
![image-20230930130110140](https://weirdo-blog.oss-cn-chengdu.aliyuncs.com/blog/202309301301231.png)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
var strStr = function(haystack, needle) { let next = [0]; for(let j = 0, i = 1; i < needle.length; i++) { while(j && needle[i] != needle[j]) j = next[j - 1]; if(needle[i] === needle[j]) j++; next[i] = j; } for(let i = 0, j = 0; i < haystack.length; i++) { while(j && needle[j] !== haystack[i]) j = next[j - 1]; if(needle[j] === haystack[i]) j++; if(j === needle.length) { return i - j + 1; } } return -1; };
|