Regular Expression Matching

题目

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
思路

面对该问题,我们的直觉应该是通过递归来解决
通过预判断下个字符,如果为*,假设该字符模式匹配若干次,将当前问题转换为子问题;否则考虑字符串和模式串的当前字符是否匹配

代码
public class Solution {
    public boolean isMatch(String s, String p) {
        if(s==null || p==null)  return false;

        return this.match(s.toCharArray(), 0, p.toCharArray(), 0);
    }

    public boolean match(char[] str, int i, char[] pattern, int j){
        if(i==str.length && j==pattern.length)  return true;

        if(j >= pattern.length) return false;

        if(j<pattern.length-1 && pattern[j+1]=='*'){
            if(match(str,i,pattern,j+2))    return true;
            while(i<str.length && (str[i]==pattern[j] || pattern[j]=='.')){
                if(match(str,++i,pattern,j+2))  return true;
            }
        }else{
            if(i == str.length) return false;

            if(str[i]==pattern[j] || pattern[j]=='.')
                return match(str,i+1,pattern,j+1);
        }
        return false;
    }
}

其实该问题也可以通过动态规划的方法解决.因为在上述递归方法中,某些子问题被重复计算,所以我们可以通过保存子问题的解来减少计算量.

假设dp[i][j]表示字符串的前i个字符与模式串的前j个字符是否匹配,考虑模式串的当前字符p[j-1]

  • 如果p[j-1]==’*’,因为该通用符可以匹配零次或若干次,所以dp[i][j]可由dp[i][j-2] 或 dp[i-1][j]与str[i-1]和p[j-2]是否匹配推导出来
  • 否则 根据dp[i-1][j-1]与str[i-1]和p[j-1]是否匹配推导

要注意dp数组的初始化,dp[0][0] = true;还要处理字符串为空,匹配串为a*b*c*的情况

代码
public class Solution {
    public boolean isMatch(String s, String p) {
        if(s==null || p==null)  return false;

        char[] str = s.toCharArray();
        char[] pattern = p.toCharArray();

        int m = str.length, n = pattern.length;
        boolean[][] dp = new boolean[m+1][n+1];

        dp[0][0] = true;
        for(int j=2; j<=n; j+=2){
            if(dp[0][j-2] && pattern[j-1]=='*')
                dp[0][j] = true;
            else    break;
        }

        for(int i=1; i<=m; i++){
            for(int j=1; j<=n; j++){
                if(pattern[j-1]=='*'){
                    dp[i][j] = dp[i][j-2] || 
                            (dp[i-1][j] && (str[i-1]==pattern[j-2] || pattern[j-2]=='.'));
                }else{
                    dp[i][j] = dp[i-1][j-1] && (str[i-1]==pattern[j-1] || pattern[j-1]=='.');
                }
            }
        }

        return dp[m][n];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值