返回

将“KMP”算法搬进JavaScript,点亮你的字符串搜索技术!

前端

“KMP”算法的魅力

“KMP”算法,全称Knuth-Morris-Pratt算法,以它的三位创作者命名,是一种高效的字符串匹配算法,以它速度快、实现简单的特点闻名于世,经常被用来解决各种字符串搜索问题。

JavaScript版的“KMP”算法

要理解JavaScript版的“KMP”算法,首先我们需要了解它的两个核心概念:

  • 前缀表(prefix table):前缀表是一个数组,用来存储每个子串的“最大公共前缀”。例如,对于字符串“ABCD”,前缀表的值为[0, 0, 0, 0],因为没有一个子串的前缀与后缀匹配。而对于字符串“ABAB”,前缀表的值为[0, 1, 1, 2],因为“AB”是“ABAB”的前缀和后缀。
  • 匹配指针(matching pointer):匹配指针是一个整数,用来标记当前正在比较的字符在“needle”字符串中的位置。

算法步骤

有了这两个核心概念,我们就可以一步一步地了解JavaScript版的“KMP”算法了:

  1. 首先,我们创建一个前缀表。
  2. 然后,我们初始化匹配指针为0。
  3. 接下来,我们开始比较“haystack”字符串中的字符和“needle”字符串中的字符。
  4. 如果字符匹配,我们增加匹配指针并继续比较下一个字符。
  5. 如果字符不匹配,我们就将匹配指针重置为前缀表中该字符对应的值,然后继续比较下一个字符。
  6. 我们重复步骤3、4、5,直到“needle”字符串中的所有字符都与“haystack”字符串中的字符匹配,或者直到我们到达“haystack”字符串的末尾。
  7. 如果我们到达了“haystack”字符串的末尾,并且“needle”字符串中的所有字符都与“haystack”字符串中的字符匹配,那么我们就找到了“needle”字符串在“haystack”字符串中的位置。
  8. 如果我们到达了“haystack”字符串的末尾,但“needle”字符串中的所有字符都与“haystack”字符串中的字符匹配,那么我们就返回-1,表示“needle”字符串不在“haystack”字符串中。

实战应用

现在,让我们用JavaScript版的“KMP”算法来解决LeetCode上的一个字符串匹配难题:

题目:给定一个字符串“haystack”和一个字符串“needle”,在“haystack”字符串中找出“needle”字符串出现的第一个位置。如果不存在,则返回-1。

function kmp(haystack, needle) {
  // 创建前缀表
  const prefixTable = [];
  prefixTable[0] = 0;
  for (let i = 1; i < needle.length; i++) {
    let j = prefixTable[i - 1];
    while (j > 0 && needle[i] !== needle[j]) {
      j = prefixTable[j - 1];
    }
    prefixTable[i] = j + (needle[i] === needle[j] ? 1 : 0);
  }

  // 匹配指针
  let matchingPointer = 0;

  // 开始比较
  for (let i = 0; i < haystack.length; i++) {
    while (matchingPointer > 0 && haystack[i] !== needle[matchingPointer]) {
      matchingPointer = prefixTable[matchingPointer - 1];
    }
    if (haystack[i] === needle[matchingPointer]) {
      matchingPointer++;
    }
    if (matchingPointer === needle.length) {
      return i - needle.length + 1;
    }
  }

  // 返回-1
  return -1;
}

调用方法:

const haystack = "ABCDABAC";
const needle = "ABAC";
const result = kmp(haystack, needle);
console.log(result); // 输出:2

结语

通过JavaScript版的“KMP”算法,我们轻而易举地找到了“ABAC”字符串在“ABCDABAC”字符串中的位置。赶紧动手实现一下,让你的字符串搜索技术更上一层楼吧!