leetcode10 正则表达式匹配

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

" . " 匹配任意单个字符
" * " 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

说明:

  • s 可能为空,且只包含从 a-z 的小写字母。*
  • p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和

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

输入:
s = "aa"
p = "a"
输出: true
解释: 因为 '
' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:

输入:
s = "ab"
p = "."
输出: true
解释: ".
" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:

输入:
s = "aab"
p = "cab"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:

输入:
s = "mississippi"
p = "misisp*."
输出: false

这是我们的题目介绍, 首先我们知道这是一个经典的dp题目, 我们我们应该确定dp状态

状态
dp[i][j] 表示 s 的前 i 个是否能被 p 的前 j 个匹配

状态转移方程
难点应该在我们的状态转移方程我们在匹配到i,j字符的时候我们比较这两个字符

  1. 如果相等或者说p(j−1)是·的情况我们直接去掉这两个字符比较前面的即可dp[i][j] = dp[i-1][j - 1]
  2. 当我们匹配到*时候我们分两种情况
    1. p前面不是•或者前面字符p[j-2]和s[i-1]字符不相等 这个时候我们匹配0个我们就让p字符的前一个进行消失,这时dp[i][j] = dp[i][j - 2]
    2. 否则的话我们就是匹配多少个的情况
      • 匹配0个 我们直接让前面的字符消失dp[i][j-2]
      • 匹配1个的情况我们就直接把当前p【j-1】的*号去掉就是比较dp[i][j-1]
      • 匹配多个的情况就是我们在s中存在多个s[i-1], 我们去掉一个s[i-1]对结果并无影响即我们可以直接求dp[i-1][j]
        得出方程dp[i][j] = dp[i][j - 2] || dp[i - 1][j] || dp[i][j - 1]

初始状态
我们需要找出匹配前面0个字符的串,即dp[0][j],我们需要循环p字符串判断当前存不存在“ * ”字符 如果存在的话我们 dp[0][j] = dp[0][j - 2]
或者我们换一种思路我们可以在这两个字符串的前面都加上一个空字符,最后的结果不会产生影响,但是我们可以省略掉中间的初始化步骤

最后给出代码

var isMatch = function(s, p) {
    //dp[i][j]表示s前i个字符能否匹配p前j个字符
    //预处理
    s = ' ' + s
    p = ' ' + p
    let m = s.length
    let n = p.length
    let dp = Array.from(new Array(m + 1), () => new Array(n + 1).fill(false))
    dp[0][0] = true
    //预处理, 我们需要找出匹配前面0个字符的串
    //for (let j = 1; j <= n; j++) {
    //    if (p[j - 1] == '*') dp[0][j] = dp[0][j - 2]
    //}
    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            if (s[i - 1] == p[j - 1] || p[j - 1] == '.') {
                dp[i][j] = dp[i - 1][j - 1]
            } else if (p[j - 1] == '*') {
                if (p[j - 2] != s[i - 1] && p[j - 2] != '.') {
                    dp[i][j] = dp[i][j - 2] //p的字符匹配不上就让他消失,即匹配0个
                } else {
                    // 匹配0个我们就让p字符的前一个进行消失,就时dp[i][j-2]
                    //匹配1个的情况我们就直接把当前p【j-1】的*号去掉就是比较dp[i][j-1]
                    //匹配多个的情况就是我们在s中存在多个s[i-1], 我们去掉一个s[i-1]对结果并无影响即我们可以直接求dp[i-1][j]
                    dp[i][j] = dp[i][j - 2] || dp[i - 1][j] || dp[i][j - 1]
                }
            }
        }
    }

    return dp[m][n]
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349