Force deduction question 10 regular expression matching (difficult)

Keywords: Java leetcode Dynamic Programming regex

Give you a string   s   And a character rule   p. Please implement a support '.'   and  '*'  Regular expression match for.

'.' matches any single character
'*' matches zero or more preceding elements
The so-called matching is to cover   whole   character string   s, not part of the string.

Example 1:

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

Example 2:

Input: s = "aa" p = "a *"
Output: true
Explanation: because '*' means that zero or more preceding elements can be matched, the preceding element here is' a '. Therefore, the string "aa" can be regarded as' a 'repeated once.

Example   3:

Input: s = "ab" p = ". *"
Output: true
Explanation: ". *" means that it can match zero or more ('*') arbitrary characters ('.').

Example 4:

Input: s = "aab" p = "c*a*b"
Output: true
Explanation: because '*' represents zero or more, here 'c' is 0, and 'a' is repeated once. Therefore, you can match the string "aab". show

Example 5:

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

1. When I do it, I compare it one by one from the front to the back, but when I encounter "aaa" and "aa*aa", it is difficult to judge, because the combination of * can not be directly obtained from the positive judgment, and the situation is complex. Therefore, there are always situations that are not considered in the program written by yourself. At this time, we should consider matching from back to front.

2. The idea of dynamic programming. You want to judge the matching of each substring first, and then judge the matching of the current string according to the current corresponding character.

    View analysis Posts written by others: Force buckle

    The code written in the comment area is posted here, from @huwd

class Solution {
    public boolean isMatch(String s, String p) {
        char[] sChar = s.toCharArray();
        char[] pChar = p.toCharArray();

        //Indicates that the first few characters match successfully, so the length is divided into sLength+1 and pelength + 1
        boolean[][] f = new boolean[sChar.length + 1][pChar.length + 1];

        f[0][0] = true;//When both strings are empty, the match is successful
        //When s is not empty and p is empty, it is false, that is, f[][0] = false;

        //When s is empty, it may also be true if p is a combination of *
        for(int j = 1;j <= pChar.length;j++){
            if(pChar[j - 1] == '*'){//p encountered*
                f[0][j] = f[0][j-2];//Because s is empty, it means that the combination composed of * appears 0 times, so minus 2
            }
        }

        //Find the matching result of each substring from bottom to top
        for(int i = 1;i <= sChar.length;i++){
            for(int j = 1;j <= pChar.length;j++){
                if(sChar[i - 1] == pChar[j - 1] || pChar[j-1] == '.'){//The characters match successfully, or the characters are
                    f[i][j] = f[i-1][j-1];
                }else if(pChar[j - 1] == '*'){//If encountered*
                    if(sChar[i-1] == pChar[j-2] || pChar[j-2] == '.'){//If the character match is successful, or the character is
                        f[i][j] = f[i][j-2] //*Combination matches 0 times
                                || f[i-1][j]; //Match 1 or more times
                    }else{//*The character matching is unsuccessful, indicating that this * combination can only be matched 0 times
                        f[i][j] = f[i][j-2];
                    }
                }
            }
        }

        return f[sChar.length][pChar.length];
    }
}

    The idea of dynamic programming is to turn big problems into small problems, and then deduce the results of big problems step by step. The difficulty in this question is the matching problem after * may be matched 0 times or multiple times, so it is relatively simple to judge one by one from the back to the front.

    Official solution:

class Solution {
    public boolean isMatch(String s, String p) {
        int m = s.length();
        int n = p.length();

        boolean[][] f = new boolean[m + 1][n + 1];
        f[0][0] = true;
        for (int i = 0; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (p.charAt(j - 1) == '*') {//If you encounter*
                    f[i][j] = f[i][j - 2];//Take the combination of * as a whole
                    if (matches(s, p, i, j - 1)) {//Judge the match between the previous character of * and the character of s
                        f[i][j] = f[i][j]//*Combination matches 0 times 
                                  || f[i - 1][j];//*Combination matching 1 or more times
                    }
                } else {//What I met was not*
                    if (matches(s, p, i, j)) {
                        f[i][j] = f[i - 1][j - 1];//Substrings are each moved forward by one character
                    }
                }
            }
        }
        return f[m][n];
    }

    public boolean matches(String s, String p, int i, int j) {
        if (i == 0) {//If s is an empty string, the matching must fail
            return false;
        }
        if (p.charAt(j - 1) == '.') {//Any character can match when encountering
            return true;
        }
        return s.charAt(i - 1) == p.charAt(j - 1);//If you encounter ordinary characters, you can compare them directly
    }
}

Question source: Force buckle

Posted by Frapster on Fri, 24 Sep 2021 02:02:08 -0700