[LeetCode#10]Regular Expression Matching

本文详细介绍了如何通过递归方式实现正则表达式的匹配功能,支持点(.)匹配任意字符及星号(*)匹配零次或多次前一字符。包括基本情况处理、单字符情况、多字符情况下的星号处理等,通过实例演示了正则表达式匹配的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值