• leetcode之路:10. 正则表达式匹配


    题目传送门:https://leetcode-cn.com/problems/regular-expression-matching/

    看懂标准题解后AC了此题,看的时候觉得很难理解,这里我尝试解释得更通俗易懂一些。

    题解用了动态规划的思想,即直接求解一定规模的问题很难思考,但该问题可以转化为一个或几个更小规模的同类问题去解决。

    我们使用 bool dp[i][j] 来代表 s 串的前 i 个字符是否与 p 串的前 j 个字符相匹配,注意,这里是前 i 个字符,即 dp[i][j] 是 s[0 ... i - 1] 与 p[0 ... j - 1] 是否匹配。

    该问题可以分成以下两种情况:

      1: p 串最后一个字符不是 * 的情况:

        此时我们只需考虑 s[i - 1] 与 p[j - 1] 是否匹配即可(注意,这里的匹配有两层含义:s[i - 1] == p[j - 1] 或者 p[j - 1] == .)。如果匹配的话,则dp[i][j] = dp[i - 1][j - 1].

    参考如下代码:

    if(p[j - 1] != '*')dp[i][j] = (match(i, j) ? dp[i - 1][j - 1] : false);

      2: p串最后一个字符是 * 的情况:

        此时又可以分成两种情况:  

    •  这个 * 当 0 个前面的字符使用:此时这个 * 和前面的字符相当于都没了,dp[i][j] = dp[i][j - 2].
    •     这个 * 当任意个( > 0) 前面的字符使用:此时,如果有s[i - 1] 与 p[j - 2] 匹配,则 dp[i][j] = dp[i - 1][j].(这里可能会有疑问,比如我:不应该是 dp[i][j] = dp[i - 1][j - 1]吗?因为 p 串的最后一个字符 * 被匹配走了呀。  答:这个 * 不一定只匹配了 s 的最后一个字符,有可能 s 的倒数第二个、倒数第三个....都是这个 * 匹配的,所以这里 dp[i][j] = dp[i - 1][j] 是合理的。) 

    参考如下代码:

    if(match(i, j - 1))dp[i][j] =  dp[i - 1][j] || dp[i][j - 2];
    else dp[i][j] = dp[i][j - 2];

    完整代码如下:

    1. class Solution {  
    2. public:  
    3.     bool isMatch(string s, string p) {  
    4.         int s_len = s.size(), p_len = p.size();  
    5.         function<bool(intint)> match = [&](int i, int j){  
    6.             if(!i)return false;//这里不用管 j 是因为遍历数组时 j 从 1 开始   
    7.             return p[j - 1] == '.' || s[i - 1] == p[j - 1];  
    8.         };   
    9.         vector<vector<int>> dp(s_len + 1, vector<int>(p_len + 1));  
    10.         dp[0][0] = true;  
    11.         for(int i = 0; i <= s_len; i++){  
    12.             for(int j = 1; j <= p_len; j++){  
    13.                 if(p[j - 1] != '*')dp[i][j] = (match(i, j) ? dp[i - 1][j - 1] : false);  
    14.                 else{  
    15.                     if(match(i, j - 1))dp[i][j] =  dp[i - 1][j] || dp[i][j - 2];  
    16.                     else dp[i][j] = dp[i][j - 2];  
    17.                 }  
    18.             }  
    19.         }   
    20.         return dp[s_len][p_len];   
    21.     }  
    22. };  
  • 相关阅读:
    【BZOJ】4671: 异或图
    【LOJ】#2035. 「SDOI2016」征途
    【UOJ】#37. 【清华集训2014】主旋律
    【LOJ】#2320. 「清华集训 2017」生成树计数
    【LOJ】#2290. 「THUWC 2017」随机二分图
    【LOJ】#2291. 「THUSC 2016」补退选
    【LOJ】 #2545. 「JXOI2018」守卫
    【LOJ】#2292. 「THUSC 2016」成绩单
    【LOJ】#2562. 「SDOI2018」战略游戏
    《linux 内核全然剖析》sched.c sched.h 代码分析笔记
  • 原文地址:https://www.cnblogs.com/peichaoL/p/13731535.html
Copyright © 2020-2023  润新知