KMP算法实现-找出字符串中第一个匹配项的下标

7 阅读1分钟

看leetCode没看懂,然后google+chatGPT基本把我讲明白

1. 思路

  1. 求取模板字符串的LPS(Longest Prefix Suffix)

// 构建部分匹配表
function buildLPS(pattern) {
  const lps = new Array(pattern.length).fill(0);
  let length = 0, i = 1;// length 为已知的最长“签证 == 后缀”长度

  while(i < pattern.length) {
    if (pattern[i] === pattern[length]) {
      length++;
      lps[i] = length;
      i++;
    } else {  
      if (length != 0) {
        // !!!! 这是关键关键!!!!
        length = lps[length - 1];//反复退回前面最长相等前后缀的方式
      } else {  
        lps[i] = 0;
        i++;
      }
        
    }
  }
}

🔍 以 "ABCDABD" 为例,打印输出:

console.log(buildLPS("ABCDABD")); 
// 输出: [0, 0, 0, 0, 1, 2, 0]

你可以逐个对应:

  • A: 无前后缀,共同长度 0
  • AB: 前[A],后[B] → 0
  • ABC: 前[A, AB],后[BC, C] → 0
  • ABCD: … → 0
  • ABCDA: 前[A, AB, ABC, ABCD],后[BCDA, CDA, DA, A] → "A" → 1
  • ABCDAB: … → "AB" → 2
  • ABCDABD: … → 无 → 0

2. 按题目求解

var strStr = function(haystack, needle) {
  if (needle.length === 0) return 0;
  let lps = buildLPS(needle);
  let i = 0, j = 0;
  while (i < haystack.length) {
    if (haystack[i] === needle[j]){
      i++;
      j++;
      if (j === needle.length) return i - j;
    } else {
      if (j != 0) {
        j = lps[j - 1]; 
      } else {
        i++;
      }
    }
  }
  return -1;
};

3. 算法复杂度

O(m+n)