LeetCode第[44]题(Java):Wildcard Matching Regular Expression Matching

Title : Wildcard Matching

Difficulty : hard

Topic content :

Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'.

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

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 *.

Translation : Given an input string (s) and a template (p), implement wildcard pattern matching and support "?" and "*".

"? matches any character.

"Matches any sequence of characters (including the empty sequence).

The match should cover the entire input string (not parts).

 

Notice:

s can be empty and contain only lowercase letters az.

p can be empty and contain only lowercase letters az, and ? or*.

 

My thoughts : This question is very similar to question 10: Regular Expression Matching , but in question 10 is ' . ' and ' * ', here is ' ? ' and ' * ',

' . ' and ' ? ' have corresponding meanings, but ' * ' means different meanings. Question 10 only represents the number. This question represents any sequence, so modify the code of question 10:

1. First_match needs to add  pattern.charAt(0) == '*'  ;

2. There are two mutually exclusive cases A and B:

A: Match with *: (At this time, there are two compatible cases )

   a1: * does not match any characters

   a2: * matches a certain character

  The result of case A is a1 || a2

B: No*:

 

my code:

 1     public boolean isMatch(String text, String pattern) {
 2         if (pattern.isEmpty()) return text.isEmpty();
 3         boolean first_match = (!text.isEmpty() && 
 4                                (pattern.charAt(0) == text.charAt(0) || pattern.charAt(0) == '?' || pattern.charAt(0) == '*'));
 5         
 6         if (pattern.charAt(0) == '*'){
 7             return (isMatch(text, pattern.substring(1)) || 
 8                     (first_match && isMatch(text.substring(1), pattern)));
 9         } else {
10             return first_match && isMatch(text.substring(1), pattern.substring(1));
11         }
12     }

Result : 1614 / 1808 test cases passed.   

Last executed input:   "aaabbbaabaaaaababaabaaabbabbbbbbbbaabababbabbbaaaaba"   "a*******b"

------Time Limit Exceeded------

It seems that the method is feasible, probably because of the use of recursion, too many *** in the middle lead to too many sub-recursions, so the operation is too slow.

 

Answer code :

 1     public boolean isMatch(String s, String p) {
 2       int m = s.length(), n = p.length();
 3       char[] sc = s.toCharArray();
 4       char[] pc = p.toCharArray();
 5       boolean[][] dp = new boolean[m + 1][n + 1];
 6       dp[0][0] = true;
 7       for(int j = 1; j < n + 1; j++){
 8         if(pc[j - 1] == '*') dp[0][j] = dp[0][j - 1]; 
 9       }   
10       
11       for(int i = 1; i < m + 1; i++){
12         for(int j = 1; j < n + 1; j++){
13           if(pc[j - 1] == sc[i - 1] || pc[j - 1] == '?'){
14             dp[i][j] = dp[i - 1][j - 1];
15           } else if(pc[j - 1] == '*'){
16             dp[i][j] = dp[i - 1][j] || dp[i][j - 1];
17           } else {
18             dp[i][j] = false;
19           }
20         }
21       }
22       return dp[m][n];
23     }

Answer complexity : O(M*N)

Answer idea : Use a two-dimensional array to record the matching status of each point. The matching status of the subsequent points depends on the current matching and the previous matching, so the matching status of the last point is the entire matching result.

The rows and columns of the array are pattern, str respectively

 

The algorithm is mainly divided into two parts:

1. Assign values ​​to row 0 and column 0:

  Column 0 - the default value is false except for the first one, which is true;

  Line 0 - if a certain position of the pattern is *, then the value corresponding to the 0th line is equal to the previous value, otherwise the default value is false.

2. Start with the element at row 1, column 1:

  If the current str value directly matches (or matches?) the value of pattern, the value of the two-dimensional array directly takes the matching result of the previous "element": [i-1][j-1]

  If the current str value and the pattern value are matched only by ''*'', the value of the two-dimensional array is equal to (the result of this element and the previous pattern || the result of this pattern and the previous element)

  If neither of the above is true, the default value is false.

 

eg. pattern = *a**a    str = bbaa

bp[][]=   ' '       *      a       *      *       a

'' [true, true, false, false, false, false]
b [false, true, false, false, false, false]
b [false, true, false, false, false, false]
a [false, true, true, true, true, false]
a [false, true, true, true, true, true]

 

Conclusion : Although the second method is good, it is too troublesome to understand, but it is also easy to remember and remember the ideas. . .

   Using the first situation in a general interview or written test is sufficient.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325842946&siteId=291194637