美文网首页
不积跬步之第四章--正则回溯法原理

不积跬步之第四章--正则回溯法原理

作者: 雨飞飞雨 | 来源:发表于2021-06-15 23:42 被阅读0次

大佬的话,学习正则表达式,是需要懂点匹配原理的。而聊到匹配原理,就说道了回溯,那么什么是回溯呢?这是我们这一章要明白的问题。

  • 什么是回溯?
  • 没有回溯的匹配是什么?
  • 有回溯的匹配
  • 常见的回溯形式

要明白什么是回溯,那需要先看一个没有回溯的匹配是什么?就明白了

没有回溯的匹配

假如我们的正则是/ab{1,3}c/,它的可视化是:

image.png

{1,3}是量词,表示要匹配1到3次的b。

假如我们要匹配abbbc

  1. 先从a出发,正好第一个字符是a,匹配成功。
  2. 接着我们从第二个字符b{1,3}.它要求字符是b,要1到3次。我们匹配到了第二个字符b
  3. 上一个条件我们满足,我们继续往下走,看看是不是可以满足2次呢?我们匹配到了第三个字符b
  4. 居然又满足,是不是可以满足3次呢?我们匹配到了第四个字符b.
  5. 前面的正则都满足,那么我就开始匹配正则下面的要求了。是不是c呢? 居然真的是???我们匹配到了第五个字符c.

至此所有正则全都匹配,没有必要重头开始。所以没有回溯匹配。

动图是这样:

image.png

有回溯的匹配

知道了没有回溯的,那么有回溯的就好理解了吧!

例如我们要匹配abbc,中间就会有回溯。

image.png

在第五步的时候,我们想要匹配b{1,3},是否满足它有3个字符时,发现它不是b而是c,那么就认为b{1,3}就已经匹配完毕。然后状态又回溯到之前的状态,也就是第六步和第四步一样。就是它回退了一步。你既然这个不满足,那么我就回退一步,重新走,看看回退一步是不是可以满足呢?

所以这里它回退了一步,从c开始出发,发现可以匹配。开心!

还可以看一个更直观的例子:

正则匹配/ab{1,3}bbc/,而我们要匹配的字符串是:abbbc

加入我们要能匹配到abbbc这个字符串,那么我们的量词条件就不能满足3的次数,而只能是1的次数。

但是正则引擎不知道呀,它只能按个试了,我先从abbb来试,看看能不能走通呢?

结果发现走到ab{1,3}的时候就走不下去了,因为它要求后面还有两个b,怎么办呢?

只能回退一步,看看条件能走下去不?结构发现abb也不能,因为它要求后面还有两个b

可是字符串不够了呀?算了,我再退一步,好吧!我要求ab后面跟着两个b可以不?

哎,可以。开心,后面是c,也可以,开心!

image.png

常见的回溯形式

正在表达式匹配字符串的这种方式,有一个学名,叫回溯法。

回溯法也称试探法,它的基本思想是:从问题的某一种状态(初始状态)出发,搜索从这种状态出发
所能达到的所有“状态”,当一条路走到“尽头”的时候(不能再前进),再后退一步或若干步,从
另一种可能“状态”出发,继续搜索,直到所有的“路径”(状态)都试探过。这种不断“前进”、 不断“回溯”寻找解的方法,就称作“回溯法”。 — 百度百科

1.贪婪量词

之前的例子中我们使用的就是贪婪量词来实现的。因为是贪婪的,所以会尽可能往多的方向去尝试,先尝试多的,{1,3},看看是不是满足3个,如果是我就继续尝试,如果不满足,我就吐出来一个,还不能满足,我就再吐。

虽然局部是贪婪的,但是也要满足整体能正确匹配。要不,要你何用呢?

如果多个贪婪量词挨着会不会冲突呢?

答案是,先下手为强:

var string = "12345";
var regex = /(\d{1,3})(\d{1,3})/;
console.log( string.match(regex) );
// => ["12345", "123", "45", index: 0, input: "12345"]

2.惰性量词

贪婪量词有回溯,你不会以为惰性量词就没有把,是否有回溯其实取决于整体的匹配,知道你容易满足,一个就够了,但是为了大局着想,还是要多给你一点。

var string = "12345";
var regex = /(\d{1,3}?)(\d{1,3})/;
console.log( string.match(regex) );
// => ["1234", "1", "234", index: 0, input: "12345"]
image.png image.png

知道你不贪、很知足,但是为了整体匹配成,没办法,也只能给你多塞点了。因此最后\d{1,3}? 匹配的字 符是 "12",是两个数字,而不是一个。

3.分支结构

我们知道分支也是惰性的,比如 /can|candy/,去匹配字符串 "candy",得到的结果是 "can",因为分支会
一个一个尝试,如果前面的满足了,后面就不会再试验了。

分支结构,可能前面的子模式会形成了局部匹配,如果接下来表达式整体不匹配时,仍会继续尝试剩下的分
支。这种尝试也可以看成一种回溯。

image.png

目标字符串candy的匹配过程是:

image.png

总结

什么是回溯法呢?

简单总结就是,正因为有多种可能,所以要一个一个试。直到,要么到某一步时,整体匹配成功了;要么最 后都试完后,发现整体匹配不成功。

  • 贪婪量词“试”的策略是:买衣服砍价。价钱太高了,便宜点,不行,再便宜点。
  • 惰性量词“试”的策略是:卖东西加价。给少了,再多给点行不,还有点少啊,再给点。
  • 分支结构“试”的策略是:货比三家。这家不行,换一家吧,还不行,再换。

相关文章

  • 不积跬步之第四章--正则回溯法原理

    大佬的话,学习正则表达式,是需要懂点匹配原理的。而聊到匹配原理,就说道了回溯,那么什么是回溯呢?这是我们这一章要明...

  • 第四章 正则表达式回溯法原理

    第四章 正则表达式回溯法原理 学习正则表达式,是需要懂点儿匹配原理的。 而研究匹配原理时,有两个字出现的频率比较高...

  • 正则表达式回溯法原理

    来源:正则表达式回溯法原理作者:老姚(转载已获得作者授权) 学习正则表达式,是需要懂点儿匹配原理的。而研究匹配原理...

  • 正则应用举例

    在写具体的案例之前,先说一个概念,正则的回溯,这个其实是正则匹配的原理,在这里给大家推荐一篇文章正则表达式回溯法原...

  • 不积跬步之正则的终章整理

    终于学习完了这一本《JavaScript正则表达式迷你书》,全书只有八十多页,而我却差不多学习了两周时间。从不熟悉...

  • 不积跬步

    2018/10/25 星期四 晴 没想到二姐的高价小收音机比手机的辐射要强,放在床边睡觉,...

  • 不积跬步

    “不积跬步无以至千里”常用来激励。 可在自己身上发掘这句名言,却只有垃圾、肥肉和慢。 一个上午,断断续续收拾了两个...

  • 不积跬步

    生活中看起不起眼的事情,对一些人来说就是财富机遇 朋友在我们单位上班,也属于从别的单位挖过来的,老板慧眼识珠,两人...

  • 点滴积累成就精彩演讲

    冰冻三尺,非一日之寒。 ——王充不积跬步,无以...

  • 不积跬步之快速排序

    快速排序使用了分治思想来实现。 和冒泡排序一样,快速排序也属于交换排序,通过元素直接的比较和交换位置来达到排序的目...

网友评论

      本文标题:不积跬步之第四章--正则回溯法原理

      本文链接:https://www.haomeiwen.com/subject/neityltx.html