字符串--KMP算法

介绍

KMP用于解决字符串匹配问题

用暴力匹配法,会产生许多回溯,每次只移动一位,若匹配不成功,就在移动一位。试想采用这样的方法,若一个给定字符串需要去进行匹配,前面的字符都匹配成功,只有最后一位匹配失败,那前面的努力不就都浪费了嘛

原理及相关概念

前缀和后缀

前缀:包含首字母,不包含尾字母的所有子串
后缀:包含尾字母,不包含首字母的所有子串

比如字符串abc,前缀就是a,ab,后缀就是c,bc

最长相等前后缀

比如字符串abac,其中a最长相等前后缀为0,ab最长相等前后缀为0,aba最长相等前后缀为1,abac最长相等前后缀为0;

这时就产生了一个前缀表0010,通过这个前缀表就可以避免一些重复匹配的过程,它的原理是利用最长相等前后缀的特性,当文本串和模式串都匹配了一些字符后,这时遇到不相等字符,模式串回退到最长相等前缀,文本串利用最长相等后缀,这样在进行比较

在这里插入图片描述

实现(JS)

力扣 28. 找出字符串中第一个匹配项的下标

// 计算字符串s的前缀表next数组
function getNext(next, s) {
  // j表示前缀末尾位置,i表示后缀末尾位置
  next[0] = 0
  let j = 0
  for (let i = 1; i < s.length; i++) {
    // 当前后缀末位位置字符不相等时,j要回退
    while (j > 0 && s[i] !== s[j]) {
      j = next[j - 1]
    }
    // 当前后缀末位位置字符相等时,i和j都要向前移动
    if (s[i] === s[j]) {
      j++
    }
    // j当前的位置就表示最长相等前后缀
    next[i] = j
  }
}

// haystack 文本串
// needle 模式串
var strStr = function (haystack, needle) {
  // 得到前缀表
  let next = []
  getNext(next, needle)

  // 遍历needle
  let index = 0

  for (let i = 0; i < haystack.length; i++) {
    // 当两个字符串匹配到有不相等的字符时,指向模式串的指针需要根据其前缀表进行回退(注意是循环,即要回退到退不动或者出现两个字符串匹配到有相等的字符)
    while (index > 0 && haystack[i] !== needle[index]) {
      index = next[index - 1]
    }
    // 当两个字符串匹配到有相等的字符时,i和index向前移动
    if (haystack[i] === needle[index]) {
      index++
    }
    // 模式串匹配结束,return下标
    if (index === needle.length) {
      return i - index + 1
    }
  }
  return -1
}

时间复杂度分析

暴力解法O(n*m),KMP算法O(n+m)
其中n为文本串长度,m为模式串长度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值