10.正则表达式匹配【剑指offer——JAVA实现】【LeetCode——JAVA实现】

版权声明: https://blog.csdn.net/lhl1124281072/article/details/79979834

题目描述

LeetCode 10

给定一个字符串 (s) 和一个字符模式 (p)。实现支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符。
'*' 匹配零个或多个前面的元素。

匹配应该覆盖整个字符串 (s) ,而不是部分字符串。

说明:

  • s 可能为空,且只包含从 a-z 的小写字母。
  • p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *

示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:
s = "aa"
p = "a*"
输出: true
解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"。

示例 3:

输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。

示例 4:

输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"。

示例 5:

输入:
s = "mississippi"
p = "mis*is*p*."
输出: false

《剑指offer》

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

解题思路

下文综合整理自牛客网,加入了自己的总结与补充。

【1】当模式中的第二个字符是“*”时:

1、如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。

如:

字符串   abc ————> abc

模式串   b*a ————>  b*a

结论:当前位不相同,一个为a,一个为b,模式串后移2位,继续比较............

2、如果字符串第一个字符跟模式第一个字符匹配(相同或者模式为'.'),可以有3种匹配方式:

(1)模式后移2字符,相当于x*被忽略;

如:

字符串   abc ————> abc

模式串   .*ac ————>  .*a

结论:该方式主要用来应对模式'.'匹配a的情况,可以看到,模式串后移2位,可以方便地继续比较............

(2)字符串后移1字符,模式后移2字符;

如:

字符串   abc  ————>  abc

模式串   a*bc ————>  a*bc

结论:该方式主要用来应对一个a匹配a*的情况,字符串后移1位,模式串后移2位,愉快地继续比较............

(3)字符串后移1字符,模式不变,即继续匹配字符下一位,因为*可以匹配多位;

如:

字符串   aaaaaaabc ————> aaaaaaabc

模式串   a*bc          ————>  a*bc

结论:该方式主要用来应对一串a匹配a*的情况,字符串后移1位,模式串不变,开心地继续比较............

【2】当模式中的第二个字符不是“*”时:

1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。

如:

字符串   abd

模式串   acd

结论:当前位相同,都为a,匹配下一个

2、如果字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。

如:

字符串   abd

模式串   acd

结论:当前位不相同,一个为b,一个为c,返回false

代码实现

public class Solution {
    public boolean match(char[] str, char[] pattern)
    {
        //如果输入为空,返回匹配失败
        if(str == null || pattern == null) return false;
        
        return match(str, pattern, 0, 0);
    }
    
    private boolean match(char[] str, char[] pattern, int strIndex, int patIndex) {
        //如果字符串和模式同时遍历完成,说明匹配成功
        if(strIndex == str.length && patIndex == pattern.length)
            return true;
        //如果字符串还没有遍历完,模式已经遍历完,说明匹配失败
        if(strIndex != str.length && patIndex == pattern.length)
            return false;
        
        //【1】当模式中的第二个字符是“*”时:
        if(patIndex < pattern.length - 1 && pattern[patIndex + 1] == '*') {
            //2、如果字符串第一个字符跟模式第一个字符匹配(相同或者模式为'.'),可以有3种匹配方式:
            if(strIndex < str.length && (pattern[patIndex] == str[strIndex] 
               || pattern[patIndex] == '.')) {
                        //(2)字符串后移1字符,模式后移2字符;
                return     match(str, pattern, strIndex + 1, patIndex + 2)
                        //(3)字符串后移1字符,模式不变,即继续匹配字符下一位,因为*可以匹配多位;
                        || match(str, pattern, strIndex + 1, patIndex)
                        //(1)模式后移2字符,相当于x*被忽略;
                        || match(str, pattern, strIndex, patIndex + 2);
            } else {
                //1、如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。
                return match(str, pattern, strIndex, patIndex + 2);
            }
        }
        //【2】当模式中的第二个字符不是“*”时:tips!!!切记要把对下标的合法性检查放在&&左侧
        if(strIndex < str.length && (pattern[patIndex] == str[strIndex]
          || pattern[patIndex] == '.')) {
            //1、如果字符串第一个字符和模式中的第一个字符相匹配
            return match(str, pattern, strIndex + 1, patIndex + 1);
        }
        //2、如果字符串第一个字符和模式中的第一个字符相不匹配,直接返回false
        return false;
    }
}

    根据思路一步步进行代码实现,果然“磨刀不误砍柴工”~


更多算法解答请点击《剑指offer》66题JAVA代码算法实现全集

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页