zoukankan      html  css  js  c++  java
  • LeetCode 10. Regular Expression Matching

    Regular Expression Matching | LeetCode OJ
    https://leetcode.com/problems/regular-expression-matching/

    这个问题的关键需要对pattern里各种字符的情况逐个讨论清楚。

    以动态规划的解法为例。假设s长度为m,p长度为n,需要一个m*n的二维数组保存P和S匹配的情况 (实际上2*n的数组应该就够了,但为了简化讨论,采用m*n的数组)。

    注意数组A[i][j]实际表示的是p[j-1]和s[i-1]的匹配情况,因为我们需要A[0][0]来表示s和p为空的情况。

    当s和p都为空,匹配是成功的,所以A[0][0] = true。

    当s不为空,p为空,匹配肯定是失败的,所以A[1..i][0] = false。

    当s为空,p不为空,如果p为"a*b*c*..."的形式,则可以匹配成功。所以当p[j-1]为'*'时,只要之前的匹配成功了,p[j-1]就可以匹配成功,因为'*'此时表示0个字串,所以p[j-2]值为多少并不重要。因此:

    if(j>1 && p[j-1] == '*'){
        A[0][j] = A[0][j-2];   
    }

    当p[j-1]为'.',只要前续匹配成功,当前匹配就一定会成功,所以:

    A[i][j] = A[i-1][j-1]

    当p[j-1]为普通字符,如果前续匹配成功且p[j-1] == s[i-1],则匹配成功。

    当p[j-1]为'*',有几种情况:

    a. 不匹配任何字符,此时匹配是否成功取决于p往前两个字符的匹配是否成功,即 A[i][j] = A[i][j-2]。

    b. 匹配1个字符,此时匹配是否成功取决于p往前一个字符是否匹配成功,即 A[i][j] = A[i][j-1]。

    c. 匹配>1个字符。此时匹配是否成功取决于当前"x*"是否匹配s[1...i-2]成功,且当前字符s[i-1]符合匹配,即A[i][j] = A[i][j-1] && (p[j-1] == s[i-1] || p[j-1] == '.')。

    具体可以用几个例子画个矩阵跑一下:

    s="aaaa", p = "a*a*"

      null a * a *
    null T F T F T
    a F T T T T
    a F F T T T
    a F F T T T
    a F F T T T

    s="aaaa", p = "a*aa"

      null a * a a
    null T F T F F
    a F T T T F
    a F F T T T
    a F F T T T
    a F F T T T

    代码如下:

     1 #include "stdafx.h"
     2 using namespace std;
     3 /* "baa", "aa" : ".*aa"
     4 "a" : "a*a*"
     5 "a", "ab" : "a*c*" 
     6 "a" : "c*a*" */
     7 class LC010_Regular_Expression_Matching{
     8 public:
     9     bool isMatch(string s, string p) {
    10         int m = s.size(), n = p.size();
    11         vector<vector<bool>> mem(2, vector<bool>(n+1,false));
    12         mem[0][0] = true;
    13         for(int j = 2; j <= n; j++){
    14             if(p[j-1] == '*'){
    15                 mem[0][j] = mem[0][j-2];
    16             }
    17         }
    18         
    19         int cur = 0, prev = 0;
    20         for(int i = 1; i <= m; i++){
    21             cur = i%2;
    22             prev = (i-1)%2;
    23             mem[cur][0] = false;
    24             for(int j = 1; j <= n; j++){
    25                 if(p[j-1] == '.'){
    26                     mem[cur][j] = mem[prev][j-1];
    27                 }else if(p[j-1] == '*'){
    28                     bool isMatch = mem[cur][j-2] || mem[cur][j-1];
    29                     if(!isMatch){
    30                         isMatch = mem[prev][j] && (p[j-2] == s[i-1] || p[j-2] == '.');
    31                     }
    32                     mem[cur][j] = isMatch;
    33                 }else{
    34                     mem[cur][j] = mem[prev][j-1] && p[j-1] == s[i-1];
    35                 }
    36             }
    37         }
    38         
    39         return mem[cur][n];
    40     }
    41 };
  • 相关阅读:
    常见http代码错误原因及处理
    tar命令详解
    Laravel笔记
    ORM要用到的数组转对象和对象转数组函数
    模块
    内置函数
    正则
    sorted 、 filter 、 map
    匿名函数、冒泡排序,二分法, 递归
    python 函数部分
  • 原文地址:https://www.cnblogs.com/k330/p/LeetCode_10_Regular_Expression_Matching.html
Copyright © 2011-2022 走看看