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 };
原文地址:https://www.cnblogs.com/k330/p/LeetCode_10_Regular_Expression_Matching.html