my raw answers for leetcode - 10. Regular Expression Matching

Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.

'.' Matches any single character.
'*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).

Note:

s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like . or *.
Example 1:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:

Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:

Input:
s = "ab"
p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".
Example 4:

Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".
Example 5:

Input:
s = "mississippi"
p = "mis*is*p*."
Output: false

 

code:

class Solution {

public:

    bool isMatch(string s, string p) {

        if(p.empty())

            return s.empty();

        else if('*'==p[1])

            return !s.empty()&&(s[0]==p[0]||'.'==p[0])&&isMatch(s.substr(1), p)||isMatch(s, p.substr(2));

        else

            return !s.empty()&&(s[0]==p[0]||'.'==p[0])&&isMatch(s.substr(1), p.substr(1));

    }

};

comment:

272 ms 15 MB Cpp

 

It's recursion.

 

Solution 2: Dynamic Programming

code:

class Solution {

public:

    bool isMatch(string s, string p)

    {

        if(p.empty()) return s.empty();

        ////first of all, all false, and dp[i][j] is true when p[j] matches s[i]

        vector<vector<bool>> dp(s.size()+1, vector<bool>(p.size()+1, false));

 

        dp[0][0] = true;//bcz '' match ''

        if(s.size()!=0&&(s[0]==p[0]||p[0]=='.')) dp[1][1] = true;

        if(p[0]=='*') dp[0][1] = true;

 

        for(int j = 1; j<p.size(); j++)

        {

            if(p[j]=='*'&&dp[0][j-1]==true) dp[0][j+1] = true;

        }

 

        for(int i = 0; i<s.size(); i++)

        {

            for(int j = 1; j<p.size(); j++)

            {

                if(p[j]==s[i]||p[j]=='.') dp[i+1][j+1] = dp[i][j];

                if(p[j]=='*')

                {

                    if(p[j-1]!=s[i]&&p[j-1]!='.'){

                        dp[i+1][j+1] = dp[i+1][j-1];

                    }else{

                        dp[i+1][j+1] = dp[i][j+1]||dp[i+1][j-1];

                    }

                }

            }

        }

        return dp[s.size()][p.size()];

    }

};

 

comment:

12 ms 8.9 MB Cpp

I use s = "aaa", p = "ab*a*c*a" to demonstrate followings:

 

1) Don't mix up "if(p.empty()) return s.empty()" with "if(s.empty()) return p.empty();". Cuz there is test cases such s="",p=".*.*".

2)s[0] is the first char of s, p[0] is the first char of p, but dp[1][1] means the first match of s[0] and p[0]. Hence vector<vector<bool>> dp has strings' size plus one in each dimension.

3)First of all we have dp[0][0] = true, that is, an initialization of dp. You may imagine that dp[0][0] means a null char before s[0] matches a null char before p[0], that's true.

4)"if(s.size()!=0&&(s[0]==p[0]||p[0]=='.')) dp[1][1] = true;"  Don't miss s.size()!=0 cuz there is test cases such s="", p=".";

5)"if(p[0]=='*') dp[0][1] = true;" Even if dp[0][1] = false is alright.

6)

        for(int j = 1; j<p.size(); j++)

        {

            if(p[j]=='*'&&dp[0][j-1]==true) dp[0][j+1] = true;

        }

Here we initialize for when s="", p=".*.*"

7)In dat main loop, when "(p[j]==s[i]||p[j]=='.')", if dp[i][j] matches, that's dp[i+1][j+1] matches.

8)When "(p[j]=='*')", "if(p[j-1]!=s[i]&&p[j-1]!='.')" means if the last p doesn't match current s and is not '.'. And "dp[i+1][j+1] = dp[i+1][j-1];" means if the numbers b4 last p matches numbers of current s(dp[i+1][j-1];). i+1 also matches j+1. For example, when i = 1, j = 6, now we have s = "aa", p = "ab*a*c*", c doesn't matches to a, but "aa" matches "ab*a*", hence if c* have 0 c, "aa" can also matches "ab*a*c*".

9)When "(p[j]=='*')", if the last p matches current s or is '.'. And "dp[i+1][j+1] = dp[i][j+1]||dp[i+1][j-1];" "dp[i][j+1]" for example when i = 1, j = 4, we have "aa" "ab*a*", d[i][j+1] is "a" matches to "ab*a*"(notice that d[i][j+1] is s[0] with p[j]), so d[i+1][j+1] that is "aa" also matches to "ab*a*".  dp[i+1][j-1] for example when i = 0, j = 4 , we have "a" "ab*a*", d[i+1][j-1] is "a" matches to "ab*", so d[i+1][j+1] that is "a" also matches to "ab*a*".

10)I highly recommend s="aaa" p="ab*a*c*a" as the test case like above to go through almost all processes of the function.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章