剑指offer(Java实现)19 - 正则表达式匹配

请实现一个函数用来匹配包括'.''*'的正则表达式。

模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次)。

在本题中,匹配是指字符串的所有字符匹配整个模式。

例如,字符串"aaa"与模式"a.a""ab*ac*a"匹配,但是与"aa.a""ab*a"均不匹配。

样例
输入:
s="aa"
p="a*"
输出:true

思路:

递归
判断多种情况。如果模式串中有星号,它会出现在第二个位置,即pattern[1] 。这种情况下,我们可以直接忽略模式串中这一部分,或者删除匹配串的第一个字符,前提是它能够匹配模式串当前位置字符,即pattern[0] 。如果两种操作中有任何一种使得剩下的字符串能匹配,那么初始时,匹配串和模式串就可以被匹配。

class Solution {
    public boolean isMatch(String s, String p) {
        if(p.isEmpty()) return s.isEmpty();
        boolean first_match = (!s.isEmpty() && 
                               (p.charAt(0) == s.charAt(0) || p.charAt(0) == '.'));
        // 如果第二个字母为‘*’的情况, 有3种情况
        // 1:s,p+2; 2:s+1,p+2; 3:s+1,p;
        if(p.length() >= 2 && p.charAt(1) == '*'){
            // 此处先判断 s 是否和 p + 2 匹配,若不匹配,则 s,p+2; s+1,p+2 不用再判断
            return (isMatch(s, p.substring(2)) || 
                    (first_match && isMatch(s.substring(1), p)));
        }else{
            return first_match && isMatch(s.substring(1), p.substring(1));
        }
    }
}

动态规划

我们用 [方法 1] 中同样的回溯方法,除此之外,因为函数 match(text[i:], pattern[j:]) 只会被调用一次,我们用dp(i, j) 来应对剩余相同参数的函数调用,这帮助我们节省了字符串建立操作所需要的时间,也让我们可以将中间结果进行保存。

class Solution {
    public boolean isMatch(String text, String pattern) {
        boolean[][] dp = new boolean[text.length() + 1][pattern.length() + 1];
        dp[text.length()][pattern.length()] = true;

        for (int i = text.length(); i >= 0; i--){
            for (int j = pattern.length() - 1; j >= 0; j--){
                boolean first_match = (i < text.length() && 
                					(pattern.charAt(j) == text.charAt(i) || pattern.charAt(j) == '.'));
                if (j + 1 < pattern.length() && pattern.charAt(j+1) == '*'){
                    dp[i][j] = dp[i][j+2] || first_match && dp[i+1][j];
                } else {
                    dp[i][j] = first_match && dp[i+1][j+1];
                }
            }
        }
        return dp[0][0];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值