LeetCode刷题日记之字符串II

60 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情
1.找出字符串中第一个匹配下标

题目描述

image.png

解题思路

1.理解前缀表及后缀表,前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串
2.构建next数组,找出needle字符串的最长相等前后缀,next数组统计每个字符的公共前后缀。
3.循环haystack字符串,使用next数组来匹配,找出第一个匹配位置

var strStr = function(haystack, needle) {
   if(needle.length === 0) return 0
   const next = new Array(needle.length);
   getNext(next,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
};

var getNext = function(next,s){
  let j = -1
  next[0] = -1;
  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[i] = j;
  }
}

2.重复的子字符串

题目描述

image.png

解题思路

本题思路与上面一题一致,构建next数组,统计每个字符的最长相等公共前后缀。循环时判断数组的长度正好可以被 (数组长度-最长相等前后缀的长度) 整除 ,说明该字符串有重复的子字符串即可

var repeatedSubstringPattern = function(s) {
  if(s.length===0) return false
  const next = new Array(s.length)
  getNext(next,s)
  const len = s.length;
  if (next[len - 1] != -1 && len % (len - (next[len - 1] + 1)) == 0) {
        return true;
  }
        return false;
};

var getNext = function(next,s){
  let j = -1
  next[0] = -1;
  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[i] = j;
  }
}