[LeetCode] 10. Regular Expression Matching

题目描述

Given an input string (s) and a pattern (p), 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).

Note:

  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like . or *.

Example 1:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

Example 3:

Input:
s = "ab"
p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".

Example 4:

Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".

Example 5:

Input:
s = "mississippi"
p = "mis*is*p*."
Output: false

 题目分析

本题考查的是给定的字符串s能否匹配给定的正则p,在本题中"."代表任意字符,"*代表它前面的字符可以出现一次或者多次"

 具体解法

先说一下我对这种题的理解:主要就是尽可能考虑多一些的情况,这样才能设计出覆盖率大的算法,首先我们要判断正则字符串p是是否为空,如果不是null,则判断长度是不是1,如果是1,判断字符串s长度是否也是1,并且能否与正则匹配,如果正则的长度不是1,判断p[1]是不是*,这样做的目的是为了判断是否有必要进入下面的while循环(不停的向后循环看能否匹配?*这种格式,注意:?*代表.*或者[a~z]*),如果p[1]不是*,说明可能是.或者是[a~z],正常进行判断即可,然后把当前位切掉,代表已经匹配完了,带入递归,如果p[1]是*,这里就要使用while进行循环切割跳转,如果s切掉一位还是与p的当前位相等,那么久继续切割,注意:每次切割之后要将?*从p中切掉和s带入递归中进行判断,这里是为了排除.*[a~z]的情况,看.*在哪里结束可以让后面的字符继续匹配,最后如果?*不能匹配接下来的字符串了,那么跳过?*,继续递归

代码演示


public class Solution1 {

    public boolean isMatch(String s, String p) {

        // 如果正则为空,判断字符串是否为空,不为空,返回null
        if (p == null || p.length() == 0) {

            return s == null || s.length() == 0;
        }

        // 如果正则为1,则判断当前位是否为相等,或者p的当前位是'.' 然后在判断s的长度是否为1,如果不是返回false
        if (p.length() == 1) {

            return s.length() == 1 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') ;
        }

        // 上面已经判断了p的长度不是1也不是0
        if (p.charAt(1) != '*') {

            // 在这里判断如果正则字符串p不为空,但是给定字符串s为空的情况
            if (s == null || s.length() == 0) {

                return false;
            }
            // 如果长度不是1,判断当前位是否相等,或者正则是. 将当前位减去进行递归
            // 注意:这里已经判断和后一位不是*,所以下一位只可能是.或者字母
            return (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.')
                    && isMatch(s.substring(1), p.substring(1));
        }
        // 如果s不是null,并且还有长度,&& s的当前位和p的当前位相同,或者p的当前位是.
        // 注意:p[1]肯定是*,因为上面已经判断过了,所以0位和1位可能是.*或者[a~z]*
        while (s != null && s.length() != 0 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.')) {

            // 如果在当前s和正则字符切掉的?*还能匹配,这是为了判断.*或者[a~z]*的情况
            if (isMatch(s, p.substring(2))) {

                return true;
            }

            // 如果剩余字符串不能和正则切掉?*匹配,那么就切掉s的当前位
            s = s.substring(1);
        }

        // 如果到达了*所能表示的末尾,也就是p[0]重复0个或者多个还是不满足的话,将当前p的0位和1位去掉,在和s带入递归
        return isMatch(s, p.substring(2));
    }

    public static void main(String[] args) {

        Solution1 s = new Solution1();
        System.out.println(s.isMatch("ab", ".*c"));
    }
}

猜你喜欢

转载自blog.csdn.net/zhttly/article/details/82780014