自学内容网 自学内容网

力扣10. 正则表达式匹配

描述

力扣10. 正则表达式匹配
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s 的,而不是部分字符串。

示例 1:

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

示例 2:
输入:s = “aa”, p = “a*”
输出:true
解释:因为 ‘*’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。

示例 3:
输入:s = “ab”, p = “."
输出:true
解释:".
” 表示可匹配零个或多个(‘*’)任意字符(‘.’)。

提示:

1 <= s.length <= 20
1 <= p.length <= 20
s 只包含从 a-z 的小写字母。
p 只包含从 a-z 的小写字母,以及字符 . 和 *。
保证每次出现字符 * 时,前面都匹配到有效的字符

方法:动态规划

思路:
因为这个正则匹配具有多样性,比如"a"可以选择匹配0个,1个或者2个,选择不同对后面的匹配影响也不一样,所以使用动态规划。
注意题干有一个地方存在歧义,"'
’ 匹配零个或多个前面的那一个元素",它表示加上前一个有效字符一起,可以匹配为0.比如"a",可以是将a也删除。
我们用isMatch[i][j]来表示s串中前i个和p串中前j个是否匹配。那么会遇到三种情况:
1.当p中第j个字符是普通字符时,则比较j和i是否一样,一样的话isMatch[i][j] = isMatch[i-1][j-1];不一样则不做处理,默认为false。
2.当p中第j个字符是 ‘.’,则属于第一种情况中的j和i一样的情况,isMatch[i][j] = isMatch[i-1][j-1];
3.当p中第j个字符是 '
', 则又要分两种情况:(1)因为 "bba
"可以匹配"bb",即"a可以整个去掉,所以我们先考虑其取0个的情况,也就是isMatch[i][j] = isMatch[i][j-2]; (2)我们需要考虑当"a"不取零时的情况,这个情况比较复杂,留到下文结合代码解释。
具体实现及注释:

class Solution {
   public boolean isMatch(String s, String p) {
       int sLength = s.length();
       int pLength = p.length();
       boolean[][] isMatch = new boolean[sLength+1][pLength+1];
       //边界情况,当双方都为0代表匹配成功。
       isMatch[0][0] = true;
       //这儿的i或者j不代表下标,代表个数,如果要表示下标还得-1;
       /* 
           这儿i从0开始,是因为存在s="",p="a*"这种情况,这种情况为真。
           而j直接从1开始不从0开始,是因为不存在s的个数不为0,而p的个
           数为0却匹配上,因为p为匹配规则,为空没有意义。
       */
       for (int i = 0; i <= sLength; i++) {
           for (int j = 1; j <= pLength; j++) {
               if (p.charAt(j-1) == '*') {
               //这行代码表示'a*'取零个时的情况。
                   isMatch[i][j] = isMatch[i][j-2];
                   //这个首先通过方法校验'*'前的那个有效字符,和s串的第i个字符是否相等,如果相等,则可能出现"abcc" 和 "abc*"这种情况,即"c*"它不取零个,而是取一个或多个,其是否匹配,就和s串退去一个c,p串不变的情况一样
                   if (endIsEqual(i, j-1, s, p)) isMatch[i][j] = isMatch[i][j] || isMatch[i-1][j];
               } else {
                   //普通字符或者是'.',直接校验
                   if (endIsEqual(i, j, s, p))  isMatch[i][j] = isMatch[i-1][j-1];
               }
           }
       }
       return isMatch[sLength][pLength];
   }

   /**
    *这个方法用于校验s串的第i个,和p串的第j个元素是否相等,相等返回真,否则返回假。
    *
    */
   boolean endIsEqual(int i, int j, String s, String p) {
       //合法性校验,i为0直接返回假
       if (i == 0) return false;
       //如果为'.'直接返回真,因为其可以为任意字符
       else if (p.charAt(j-1) == '.') return true;
       else return s.charAt(i-1) == p.charAt(j-1); 
   }
}

原文地址:https://blog.csdn.net/dastatham/article/details/142427100

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!