代码随想录算法训练营day9 | 28. 实现 strStr 、 459.重复的子字符串、 字符串总结 、 双指针回顾

文章介绍了如何使用KMP算法解决两个字符串匹配问题,包括经典的strStr函数实现和检查重复子字符串的函数。文章提供了两种版本的KMP算法实现,分别是前缀表统一减一和不减一的情况,并讨论了next数组的理解难点。
摘要由CSDN通过智能技术生成


学习时间:

  • 晚上 八点—晚上十点

28. 实现 strStr 

题目链接/文章讲解/视频讲解

思路:

本题是KMP 经典题目。KMP的经典思想就是:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。

代码实现:

 //前缀表统一减一
    var strStr = function (haystack, needle) {
      if (needle.length === 0) {
        return 0;
      }
      const getNext = (needle) => {
        let next = [];
        let j = -1;
        next.push(j);
        for (let i = 1; i < needle.length; ++i) {
          while (j >= 0 && needle[i] !== needle[j + 1]) {
            //向前回退
            j = next[j]

          }
          if (needle[i] === needle[j + 1]) {
            j++
          }
          next.push(j)
        }
        return next
      }
      let next = getNext(needle)
      let j = -1;
      for (let i = 0; i < haystack.length; ++i) {
        while (j >= 0 && haystack[i] !== needle[j + 1]) {
          j = next[j]
        }
        if (haystack[i] === needle[j + 1]) {
          j++
        }
        if (j === needle.length - 1) {
          return (i - needle.length + 1)
        }
      }
      return -1
    };
    // console.log(strStr("sadbutsad", "sad"))

    //前缀表不统一减一
    var strStrNew = function (haystack, needle) {
      if (needle.length === 0) {
        return 0;
      }
      const getNext = (needle) => {
        let next = [];
        let j = 0;
        next.push(j);
        for (let i = 1; i < needle.length; ++i) {
          while (j > 0 && needle[i] !== needle[j]) {
            //向前回退
            j = next[j - 1]

          }
          if (needle[i] === needle[j]) {
            j++
          }
          next.push(j)
        }
        return next
      }
      let next = getNext(needle)
      let j = 0;
      for (let i = 0; i < haystack.length; ++i) {
        while (j > 0 && haystack[i] !== needle[j]) {
          j = next[j - 1]
        }
        if (haystack[i] === needle[j]) {
          j++
        }
        if (j === needle.length) {
          return (i - needle.length + 1)
        }
      }
      return -1
    };

 459.重复的子字符串

题目链接/文章讲解/视频讲解

思路:只需要判断,以第一个字母为开始的子串就可以,所以一个for循环获取子串的终止位置就行了。 而且遍历的时候 都不用遍历结束,只需要遍历到中间位置,因为子串结束位置大于中间位置的话,一定不能重复组成字符串。

代码实现:

  //前缀表统一减一
    var repeatedSubstringPattern = function (s) {
      if (s.length === 0) {
        return false
      }
      const getNext = (s) => {
        let next = []
        let j = -1;
        next.push(j)
        for (let i = 1; i < s.length; ++i) {
          while (j >= 0 && s[i] !== s[j + 1]) {
            j = next[j];
          }
          if (s[i] === s[j + 1]) {
            j++
          }
          next.push(j)
        }
        return next

      }
      let next = getNext(s)
      if (next[next.length - 1] !== -1 && s.length % (s.length - (next[next.length - 1] + 1)) === 0) {
        return true
      }
      return false
    };
    //前缀表统一不减一
    var repeatedSubstringPattern = function (s) {
      if (s.length === 0) {
        return false
      }
      const getNext = (s) => {
        let next = []
        let j = 0;
        next.push(j)
        for (let i = 1; i < s.length; ++i) {
          while (j > 0 && s[i] !== s[j]) {
            j = next[j - 1];
          }
          if (s[i] === s[j]) {
            j++
          }
          next.push(j)
        }
        return next

      }
      let next = getNext(s)
      if (next[next.length - 1] !== 0 && s.length % (s.length - (next[next.length - 1])) === 0) {
        return true
      }
      return false
    };

总结:

初次接触kmp算法 感觉十分困难 next数组那里不太好理解 二刷时会重点关注,并着重复习

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值