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 is empty and contains only lowercase letters a-z
.
p
Could is empty and contains only lowercase letters a-z
, and characters like ?
or *
.
Example 1:
input:s = "AA" p = "a" output:falseexplanation: "A" does not match the entire string "AA".
Example 2:
input:s = "AA" p = "*" output:trueexplanation: ' * ' matches any sequence.
Example 3:
Input:s = "CB" p = "? A" output:falseexplanation: '? ' matches ' C ', but the second-letter was ' a ', which does not match ' B '.
Example 4:
input:s = "Adceb" p = "*a*b" Output:trueExplanation:The first ' * ' matches the empty sequence, while the second ' * ' matches The substring "DCE".
Example 5:
input:s = "ACDCB" p = "A*c?b" Output:false
The regular matching problem is a kind of uncertain finite state automata construction. The subject is a wildcard match, but is similar to a regular match. As long as the problem can be built out of the solution. Before trying to build, let's see how the automata simulates regular matching. The first thing to do is to identify the special character '? ' What the difference is with ' * '. ‘?‘ It is well understood that it can match any single non-null character. and ' * ' can match any string (including an empty string). That is, as long as ' * ' appears, it can either make the automaton run backwards, creating a backward path, or the next state of the automaton back to its place, that is, creating the latter node back to its own path. Because it can match any string, that is, when needed, it can "absorb" all the characters that make the automaton stagnate. For example, the fourth example constructs a P-string automaton as follows:
This is where a solid node is added as an end point. If S is all scanned and p finally reaches the end point, the match succeeds. Before simulating an automaton, it is clear that the automaton is always running towards a successful target, that is, to prioritize the match before moving the pointer downward. If they do not match, consider whether they have either a backward or a forward path because of ' * '. And if the S string cannot go forward because of a mismatch, it can only be stopped once. Here is a special explanation: if the S string encounters a character, and the P string encounters ' * ', although I can move down at this time (because p corresponds to ' * '), or not, then the principle of matching priority downward movement, I is at this point should first stop in place, only J can move downward. If the next character of P still cannot match the character of S, then the pointer J of P will go back to ' * ' along with the forward path due to ' * ', and I have already stayed here, so this time we can not follow the principle of matching to move downward, after all, it is not no way to go, it can downward. If it does not want to, it will produce a dead loop. That's a mouthful, or for example 4, the new two pointers I and J,i and J respectively point to the first character of the S string and the P-string automaton, simulating the following:
1. ' A '/J ' * ': mismatch occurs because the P string is pointing to a character that is ' * ', so s and p simultaneously produce a downward path, but since this is the first time I to this position, in line with the principle of matching precedence, I stay in situ, only J-shift. And also because this time the character is ' * ', produces the next character to backtrack to the current position of the path;
2. I-a ' a '/J ' a ': Find a match, S-string and P-string pointer at the same time move backwards;
3. ' d '/j ' * ': mismatch occurs because the P string is pointing to a character that is ' * ', so s and p simultaneously produce a downward path, but since this is the first time I to this position, in line with the principle of matching precedence, I stay in place, only J-shift. And also because this time the character is ' * ', produces the next character to backtrack to the current position of the path;
4. I-, ' d '/J-A ' B ': mismatch occurs, because it does not match, and P is not pointing to ' * ', so I can not go backwards, J also can not be backward, in order to ensure that the machine operation, J can only follow the previously generated path back to the previous position, that is, J back to the second
5. ' d '/j ' * ': mismatch occurs because the P string is pointing to a character that is ' * ', so s and p simultaneously produce a downward path, this is the second time I go to this position, so I must run backwards to avoid the dead loop, so I move backward. J also move back (in fact, J can not move back, but if J stays in the ' * ', then the next step must be I point to the character and the ' * ' does not match and cause J to move back, so at this time it is better to directly after J move to the next position of ' * ', and then omit a step);
6. ' C '/J ' B ': At this point, as in the 4th step, J goes back first, because it is not a match to stay in place once, and then the next step requires and J to move back. So the final result is the same status as the 5th step (i-C '/J '), I and J are backward at the same time, i.e. I move from ' C ' to the last character ' B ', and J moves back from ' * ' to ' B ';
7. I-B '/J ' B ': Find a match, S-string and P-string pointer simultaneously move to the right. At this point P has moved to the solid end point, and S is also fully scanned, returning match true.
The simulation comes from a motive run, which proves that this is the process of finding a match, so the following is the start of building a self-motive:
First, based on the principle of priority matching and post-shift, if s[i] = = P[j], then I and J move back at the same time. Here you can put the character '? ' Add in, because you meet '? ' Exactly the same as when the match was encountered, so s[i] = = P[j] | | P[J] = = '? ', I and J move back;
If it does not match, but J points to ' * ', then do three things: 1) build the loop of P, 2) mark the position of the moment I because of the mismatch priority, so that I will not have a road next time not go; 3) move back J. At this point, we will introduce two variables, one to store the position where J points, to build the loop. One to record the position of I, to remind me next time do not have a way to go. That is, Pstar = J;sstar = i;j++;
Also if it does not match, but I is not no way to go (that is, Sstar exists), then I go to the next position of Sstar. Since Sstar exists, Pstar must exist (since both are established), then J is now going to the position of pstar+1 (for the reasons explained in brackets in step 5);
If I and J do not match there is no way to go, then can only return false, that is, s and P can not match anyway.
The process of building the automaton is also the process of completing the code, as explained in the following code.
Java
classSolution { Public BooleanIsMatch (String s, String p) {Char[] S = S.tochararray (), P =P.tochararray (); inti = 0, j = 0, Sstar =-1, Pstar = 1; while(I <s.length ()) { if(J < P.length () && (s[i] = = P[j] | | P[J] = = '? ')) {//if matched, the two pointers move back at the same timei++; J++; } Else if(J < P.length () && p[j] = = ' * ') {//if it does not match but J points to ' * ', then record the position of J at this time to build the loop, while recording the position of I to mark I can then move back but stay at this time, and J move backPstar = j + +; Sstar=i; } Else if(Sstar >= 0) {//still does not match, but I have a way to go, and I have stopped at that time, then I want to move back, along with I stop position also to update, J directly to the back of the loop ' * ' position. At this point J can also take Pstar, but the speed will be slowj = Pstar + 1; I= ++Sstar; } Else return false;//still does not match, I and J have no way to go, return false } while(J < P.length () && p[j] = = ' * ') j + +;//I scan to see if J can not reach the end point, that J can travel along the ' * ' path has been downward returnj = = P.length ();//I and J reach the finish line at the same time . }}
(Java) Leetcode 44. Wildcard matching--Wildcard Match