JavaScript shift-and算法学习笔记

shift-and算法是基于kmp算法灵感的改进,建议先去了解kmp算法

kmp的核心是找到模式串一样的前缀后,以此信息在遍历母串的时候,做一些跳过操作,达到优化结果



const shift_and = (text, pattern) => {
  /*******   模式串处理-start *******/
  let p_len = pattern.length;

  //code存储的是模式串中,当前字符出现过的位置
  //需要注意的是,遍历字符串都是从左到右,对应存储二进制数字的低位到高位
  //如'abcac'中的c 最终code数据是10100
  let code = {};
  //console.log(code);
  for (i = 0; i < p_len; i++) {
    code[pattern[i]] |= 1 << i; // 这是简写,不简写拆分开来是下面的代码

    //模式串遍历到第i的字符,说明肯定是存在的,并且一定处于i位数二进制的最高位
    //move是需要往左移动的i位后的二进制
    // const move = 1 << i;
    //通过下面一行打印可以看到,i=0时,二进制move=1;i=1时,二进制move=10;i=2时,二进制move=100...
    // console.log(move.toString(2));
    //通过以下二进制或运算,得到并更新字符的二进制数字标记
    // code[pattern[i]] = code[pattern[i]] | move;
  }

  //查看处理完毕模式串后得到的二进制数据,可以打开一下三行注释,方便理解对于模式串的处理
  //   Object.keys(code).forEach((key) => {
  //     console.log(key, code[key].toString(2));
  //   });
  /*******   模式串处理-end *******/
  let s_len = text.length;
  let p = 0; //初始化p
  //p存储的是二进制数据,信息解释:(这个意义很难理解)
  //二进制是1的位置,如第n位是1,同时第m位也是1,则前第n个字符,是母串的后缀,同时是模式串前缀,第m个字符也一样

  //如p位001010的时候,前2个字符,和前4个字符是母串的后缀,同时是模式串前缀
  for (let i = 0; i < s_len; i++) {
    // 获取上一次的p,向左移动一位(因为正在按顺序遍历字符,i每次++,就左移动一位),
    // 并且个位数添加1(因为正在遍历字符text[i])
    // 拿当前的 字符预处理的二进制跟以上的p做交操作比较
    p = ((p << 1) | 1) & code[text[i]];
    // console.log(p.toString(2));
    //理解p存储信息的意思,就可以明白以下代码的判断理由了
    if (p & (1 << (p_len - 1))) return i - p_len + 1;
  }
  return -1;
};

console.log(shift_and("ababcac", "abcac"));

console.log(shift_and("annual_announce", "announce"));

图片转载至https://www.iteye.com/blog/wlh0706-163-com-1845919
图片转载至https://www.iteye.com/blog/wlh0706-163-com-1845919

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值