剑指OFFER笔记_19_正则表达式匹配_JAVA实现

题目:正则表达式匹配

  • 请实现一个函数用来匹配包含’.‘和’*‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’*'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但与"aa.a"和"ab*a"均不匹配。

解题思路

  1. 此题可以利用动态规划法。因为它满足应用动态规划法的两个必要条件,一个是可以划分为比较小的问题,使其容易求解;二是可以将答案重新组合起来形成最终的答案。
  2. 本题可以采用从后往前缩小和从前往后缩小范围两种。我采用了从后往前。
  3. 首先检测string和pattern的最后一位。此时有三种情况:
    1. pattern的最后一位为字母。这是一种简单情况,只需要去使其和string最后一位作比较。若相同,则string和pattern将长度减1,继续检测之前的部分是否匹配,若不同,直接返回false。
    2. pattern的最后一位为’.’。这也是一种简单情况,只需要string还有字符去匹配就也可以分别将长度减1,继续检测。
    3. pattern的最后一位为’*’。这种情况下,‘*’需要分三种情况去看待。
      1. ‘*‘前的元素匹配了0次。此时将string的下标上限不变,pattern的下标上限-2,略过’*’,继续检测。
      2. ‘*‘前的元素匹配了1次。此时将string的下标上限减1,pattern的下标上限-2,略过’*’,继续检测。
      3. '*'前的元素匹配了超过1次。此时将string的下标上限减1,pattern的下标上限不变,继续检测。
  4. 在加上一些边界情况的判断即可以写出代码了。

代码

函数主体部分代码

package q19;

public class Solution {
    public boolean isMatch(String s, String p) {
        if (s == null || p == null)
        {
            return false;
        }
        if (s.length() == 0 && p.length() == 0)
        {
            return true;
        }
        char[] schar = s.toCharArray();
        char[] pchar = p.toCharArray();

        return Match(schar, pchar, schar.length-1, pchar.length-1);
    }

    public boolean Match(char[] string, char[] pattern, int sindex, int pindex)
    {
        //若字符串和模式全部消除,则返回true
        if (sindex <= -1 && pindex <= -1)
        {
            return true;
        }

        //若字符串未全部消除,模式已经全部消除,返回false
        if (sindex > -1 && pindex <= -1)
        {
            return false;
        }

        //若字符串已全部消除,模式未全部消除,单独考虑
        if (sindex <= -1 && pindex > -1)
        {
            return checkPatternForEmptyString(pattern, pindex);
        }

        //字符串和模式都有剩余的情况。
        //若模式结尾是字母,检测与字符串结尾是否匹配,不匹配返回false,匹配则递归调用,index同时减1
        if (pattern[pindex] != '.' && pattern[pindex] != '*')
        {
            if (string[sindex] != pattern[pindex])
            {
                return false;
            }
            return Match(string, pattern, sindex-1, pindex-1);
        }

        //若模式结尾是'.',任意情况都可以index同时减1
        if (pattern[pindex] == '.')
        {
            return Match(string, pattern, sindex-1, pindex-1);
        }

        if (pattern[pindex] == '*')
        {
            //若可以匹配上,分两种情况
            if (string[sindex] == pattern[pindex-1] || pattern[pindex-1] == '.')
            {
                return Match(string, pattern, sindex-1, pindex) ||
                        Match(string, pattern, sindex-1, pindex-2) ||
                        Match(string, pattern, sindex, pindex-2);
            }
            //若匹配不上,则视'*'为0次
            else
            {
                return Match(string, pattern, sindex, pindex-2);
            }
        }
        return false;
    }

    /**
     * 此函数检测此段模式是否可以匹配空字符串
     * @param pattern   模式
     * @param pindex    此段模式的下标上限
     * @return          若能匹配空字符串,返回true。若不能,返回false。
     */
    public boolean checkPatternForEmptyString(char[] pattern, int pindex)
    {
        //只有当pattern中是.*或a*的组合时才能返回true
        for (int i = 0; i <= pindex; i++)
        {
            if (pattern[i] != '*')
            {
                //最后一位必须是*,否则不可能匹配空字符串
                if (i == pindex)
                {
                    return false;
                }else
                {
                    if (pattern[i+1] != '*')
                    {
                        return false;
                    }
                }
            }
        }
        return true;
    }
}

测试部分代码

package q19;

public class TestApp {
    public static void main(String[] args) {
        Solution s = new Solution();
        String[] str = new String[5];
        String[] pat = new String[5];

        //false
        str[0] = "aa";
        pat[0] = "a";

        //true
        str[1] = "aa";
        pat[1] = "a*";

        //true
        str[2] = "ab";
        pat[2] = ".*";

        //true
        str[3] = "aab";
        pat[3] = "c*a*b";

        //false
        str[4] = "mississippi";
        pat[4] = "mis*is*p*";

        for (int i = 0; i < 5; i++) {
            System.out.println(s.isMatch(str[i], pat[i]));
        }
    }
}

运行结果截图

在这里插入图片描述

LeetCode运行截图

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值