[LeetCode#10]Regular Expression Matching

Problem:

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).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true

Analysis:

This question is really not hard if you use DFS way to match the string. (not dynamic programming!)
The most challengeing part is to clearly differentiate different cases.
Basic idea: (recursive)
1. iff p.charAt(1) = '*', it means we can use p.charAt(0) to match zero or more characters(susscive) in the s. Then continue to compare the remaining part.
2. iff p.charAt(1) != '*', it means we can don't need to care p.charAt(1), we can soly compare the p.charAt(0) and s.charAt(0). The key point is that if p.charAt(1) = '*', it can affect the match of p.charAt(0), thus we must treat it carefully. 

Like other matching problems, use s to match aginst p!!!! It is better for us to write the checking condition based on p. 
Detail:
1. base case (when p is "") <this is where a success match ends with>
It means all p's characters have already been matched.
Iff s is also "", it means p and s perfectly matched. Otherwise, we return false for this branch.
----------------------------------------------------------------------    
if (p.length() == 0)
    return s.length() == 0;
----------------------------------------------------------------------    
Note: this check is very common for following situations, p and s must perfectly match with each other. 


2. when p has only one character.
iff s is null, return false,
iff s is not null, we check if s.charAt(0) == p.charAt(0) or p.charAt(0) = '.'.
    iff not we return false;
    iff yes, we continue to compare remaining part.
----------------------------------------------------------------------    
if (p.length() == 1) {
    if (s.length() == 0)
        return false;
    else if (p.charAt(0) != '.' && p.charAt(0) != s.charAt(0))
        return false;
    else 
        return isMatch(s.substring(1), p.substring(1));
}
----------------------------------------------------------------------    
Note: you may notice that we do not have following logic:
if (s.length () > 1)
    return false;
This case would finally be hanlded at "return isMatch(s.substring(1), p.substring(1));". The reason why do not write in that way is to use the power of recursive and not to break it is code structure.


3. when p has more than one character.
3.1 p.charAt(1) != '*'
    Following the same checking in 2.
Note: we don't bother the check p.charAt(1) = s.charAt(1) at this step.
----------------------------------------------------------------------    
if (p.charAt(1) != '*') {
    if (s.length() < 1)
        return false;
    if (p.charAt(0) != '.' && p.charAt(0) != s.charAt(0))
        return false;
    else 
        return isMatch(s.substring(1), p.substring(1));
}
----------------------------------------------------------------------    

3.2 p.charAt(1) == '*'
3.2.1 we use the case: '*' represent no pre character(this is the hardest case using other method)
   if (isMatch(s, p.substring(2)))
                return true;

3.2.2 '*' represent one (more) pre charcter (many times)
int index = 0;
while (index < s.length() && (s.charAt(index) == p.charAt(0) || p.charAt(0) == '.' )) {
    if (isMatch(s.substring(index+1), p.substring(2)))
        return true;
        index++;
    }
return false;

Note: '.' can represent as many characters as possible in s.

Solution:

public class Solution {
    public boolean isMatch(String s, String p) {
        if (p.length() == 0)
            return s.length() == 0;
        if (p.length() == 1) {
            if (s.length() == 0)
                return false;
            else if (p.charAt(0) != '.' && p.charAt(0) != s.charAt(0))
                return false;
            else 
                return isMatch(s.substring(1), p.substring(1));
        }
        //at least two characters left at p
        if (p.charAt(1) != '*') {
            if (s.length() < 1)
                return false;
            if (p.charAt(0) != '.' && p.charAt(0) != s.charAt(0))
                return false;
            else 
                return isMatch(s.substring(1), p.substring(1));
        } else{
            if (isMatch(s, p.substring(2)))
                return true;
            int index = 0;
            while (index < s.length() && (s.charAt(index) == p.charAt(0) || p.charAt(0) == '.' )) {
                if (isMatch(s.substring(index+1), p.substring(2)))
                    return true;
                index++;
            }
            return false;
        }
    }
}
原文地址:https://www.cnblogs.com/airwindow/p/4783022.html