LeetCode !!!10. Regular Expression Matching

某热心大佬给的解释,图文并茂

10. Regular Expression Matching
Given an input string s and a pattern p, implement regular expression matching with support for '.' and '*' where:

'.' Matches any single character.​​​​
'*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).

 

Example 1:

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

思路:一个样本做行,一个样本作列的对应模型。
dp[i][j] 表示 字符串s的前i个字符,即str[0…i-1],与字符串p的前j个字符,即ptr[0…j-1],的匹配是否成功。

  • 先分析 末尾的两个字符(str[i-1], ptr[j-1])能不能配得上;
    • 如果str[i-1], ptr[j-1]配不上,再分析
      ptr[j-1]是不是'*', 它需要配合前一个 字符 即ptr[i-2]一起使用。
      - 如果不是,那么dp[i][j]=false;
      - 否则(即ptr[j-1]为’*'),检查ptr[i-2]==str[i-1]成立么,
      如果不成立,那么dp[i][j] =dp[i]][j-2] ( 表示ptr[j-2,j-1] 要替换成0个str[i-1])
      如果ptr[i-2]==str[i-1]成立,
      进一步地,分析 ptr[j-2,j-1] 要替换成几个str[i-1],代码中分为“替换成0个”和“替换成1个及其以上两大类”。

注:
对于测试用例s = "aabc", p=".*",答案是True. 理由: ".*"可以视为....,进一步地,每个点可以换成任何字符,所以 可以得到 “aabc”。
当使用“x*”替换为 >=1个的“x”时,可以把“x*”看作“x* x”,所以可以有下面这种情况的第二个分支的结论:
str[…i-2,i-1]与ptr[…j-2,j-1]做匹配时,其中str[i-1]=“x”, ptr[j-2,j-1]=“x*”。
第一个分支:如果ptr[j-2,j-1]准备替换成0个“x”,那么dp[i][j] =dp[i][j-2];
第二个分支:如果ptr[j-2,j-1]准备替换成 >=1个“x” ,那么dp[i][j] =dp[i-1][j]
(也就是 ptr[j-2,j-1]=“x*”生成 “x* x”,把最后一个“x”与str[i-1]消掉,但是 ptr不变,ptr[j-2,j-1]=“x*”, 然后看 str[…i-2]与ptr[…j-2,j-1]的匹配问题,即dp[i-1][j])
小汇总: dp[i][j] = dp[i][j-2]||dp[i-1][j];

  public boolean isMatch(String s, String p) {
        char[] str = s.toCharArray();
        char[] ptr = p.toCharArray();

        int slen = str.length,plen=ptr.length;
        boolean[][] dp = new boolean[slen+1][plen+1];
        dp[0][0] = true; // dp[i][j], str[0..i-1] match ptr[0..j-1]
        // dp[1...slen-1][0] is false

        // dp[0][>0], dp[0][1] = false
        for(int j=2;j<=plen;j++){
            if(ptr[j-1]=='*'){
                dp[0][j] = dp[0][j-2];
            }            
        }

        for(int i=1;i<slen+1;i++){
            for(int j=1;j<plen+1;j++){
                if(str[i-1]==ptr[j-1]||ptr[j-1]=='.'){
                    dp[i][j] = dp[i-1][j-1];
                }else {
                    if(ptr[j-1]=='*'){
                        if(str[i-1]==ptr[j-2]||ptr[j-2]=='.'){
                           dp[i][j] = dp[i][j-2]||dp[i-1][j];// 分别对应 ptr[j-2,j-1]替换成0个, 1个以上str[i-1]
                        }else{//  ptr[j-2,j-1]替换成0个                            
                             dp[i][j] = dp[i][j-2];
                        }
                    }else{// str[i-1]真的配不出来
                        dp[i][j] = false;
                    }
                }
                
            }
        }
        return dp[slen][plen];
    }

你可能感兴趣的:(数据结构与算法,leetcode,算法)