前端算法(10)

59 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

  • '.'匹配任意单个字符
  • '.'匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

输入: s = "aa", p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

解题思路

思路一

.*符合常规正则匹配,因为是对整个字符串进行校验,所以首要加^开始,尾要$终止, 如果题目还有其他不常规的匹配条件,可以先把p替换成常规的条件即可。

var isMatch = function (s, p) {
    return new RegExp(['^', p, '$'].join('')).test(s);
};

思路二

我们这里还可以使用递归方式实现

let isMatch = (s,p)=>{
    //边界问题如果s和p都为空,满足
    if(p.length<=0){
        return !s.length
    }
    let match = false
    //判断第一个字符是否匹配,首先保证s不能为空,否则无法匹配,然后开始比较s和p的第一个字符,如果p[0]是‘.’,代表匹配所有字符,也满足
    if(s.length>0&&(p[0]===s[0]||p[0]==='.')){
        match = true
    }
    //p带模式
    if(p.length>1&&p[1]==='*'){
        //两种情况
        //第一种p*为0
        //第二种p*为多个
        return isMatch(s,p.slice(2)) || (match&&isMatch(s.slice(1),p))
    }else {
        return match&&isMatch(s.slice(1),p.slice(1))
    }
};

思路三

我们先根据规则p生成匹配图表,然后再根据图表去消耗待匹配的字符串,在遇到*时,查找出可匹配的字符有几个,并从0到count开始递归消耗字符串,若全部返回false则为false,若有一个为true则视为次规则可以匹配此字符串

const toMatchArr = function(p){
  const matchArr = [];
  p.forEach((item) =>{
    if (item==='*') {
      matchArr[matchArr.length-1] += '-*';
    }else{
      matchArr.push(item)
    }
  })
  return matchArr;
}
const findCount = function(s,tar){
  if(tar==='.') return s.length;
  let count = 0;
  while(tar === s[count]){
    count++;
  }
  return count;
};
const subStrWithMatch = function(s, matchArr){
  while(matchArr.length){
    const match = matchArr.shift();
    if (match.length===1){
      const sub = s.shift();
      if (sub && (match[0]===sub || match[0]==='.')){
        return subStrWithMatch(s, matchArr);
      }else{
        return false;
      }
    }else{
      const count = findCount(s, match[0]);
      if(count===0) continue;
      let i = 0;
      while(count>=i){
        if (i) s.shift();
        if (subStrWithMatch([...s], [...matchArr])){
          return true;
        }
        i++;
        continue;
      }
      return false;
    }
  }
  if (s.length) return false;
  return true;
}
const isMatch = function(s, p) {
  p = p.split('');
  s = s.split('');
  return subStrWithMatch(s, toMatchArr(p));
};