LeetCode -- question 44 -- wildcard matching

Keywords: Asterisk

Wildcard matching

Difficulty 368

Given a string (s) and a character pattern (p), implement a wildcard match that supports'? 'and' * '.

'?' can match any single character.
'*' can match any string, including empty strings.

Only when two strings match exactly can the match be successful.

explain:

  • s may be empty and contain only lowercase letters from a-z.
  • p may be empty and contain only lowercase letters from a-z, as well as the characters? And *.

Example 1:

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

Example 2:

Input:
s = "aa"
p = "*"
Output: true
 Explanation: '*' can match any string.

Example 3:

Input:
s = "cb"
p = "?a"
Output: false
 Explanation: '?' can match 'c', but the second 'a' cannot match 'b'.

Example 4:

Input:
s = "adceb"
p = "*a*b"
Output: true
 Explanation: the first '*' can match the empty string, and the second '*' can match the string "dce"

Example 5:

Input:
s = "acdcb"
p = "a*c?b"
Output: false

 

Topic analysis:

It was intended to use recursion here, similar to the "regular expression" in the sword finger offer. Here are mainly divided into the following situations. The difficulties are mainly concentrated in the case of '*', so to analyze. Originally, I intended to use for loop to implement one by one in recursion, but I found that it couldn't work. This implementation method is contrary to my idea. It needs a few characters after '*' to match the characters in the s string, similar to the s string "abc ABC" and the p string "a*abc". Then the abc of the p string must match the last abc in the s string, so the for loop cannot be used.

The double pointer and greedy algorithm are used to solve the problem. connect: https://leetcode-cn.com/problems/wildcard-matching/solution/44-tong-pei-fu-pi-pei-shuang-zhi-zhen-by-guohaodin/

 

Reference code: (self improved recursion, but it seems that because there is no return value, the force button fails, vs can run)

class Solution {
public:
	bool isMatch(string s, string p) {
		return my_isMatch(s, p, 0, 0, 0, 0);
	}

	bool my_isMatch(string s, string p, int i, int j, int istart, int jstart)
	{
		if (s.empty() && p.empty())
			return true;

		if (s.empty() || p.empty())
			return false;

		if (p[j] != '*')
		{
			if (p[j] == s[i] || p[j] == '?')
				return my_isMatch(s, p, i + 1, j + 1, istart, jstart);
			else
				return false;
		}
		else if (p[j] == '*')
		{
			if (p.size() == 1)
				return true;

			istart = i;
			jstart = j++;
		}
		else if (istart >= 0)
		{
			i = ++istart;
			j = jstart + 1;
		}
		else return false;
	}
};

 

Reference code: (double pointer plus greedy algorithm)

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <deque>
#include <stack>
#include <algorithm>
#include <map>

using namespace std;


//If the characters in s and p match, i and j will increase automatically respectively
//Otherwise, if the current character in p is an asterisk, iStar and jStar will be marked, and j will be increased automatically
//Otherwise, if ISTAR > = 0, it means that the asterisk has been matched before. Since the asterisk can match any string, continue to increment i, and move j to the next character of jStar
//Otherwise, return false
class Solution {
public:
	bool isMatch(string s, string p) {
		//I i s the pointer of S, j is the pointer of p
		//iStar records the current i position when '*' is encountered in p
		//jStar records the current j position when '*' is encountered in p
		int i = 0, j = 0, iStar = -1, jStar = -1, m = s.size(), n = p.size();
		//Under the condition that i pointer does not reach m
		while (i < m)
		{
			//If the current character matches or p[j] is "no"? Both pointers point to the next character
			if (j < n && (s[i] == p[j] || p[j] == '?'))
			{
				++i;
				++j;
			}//Judge if p[j] is' * ', use iStar to record the position of i, jStar to record the position of j, i will not move, j will move backward to match the current i
			else if (j < n &&  p[j] == '*')
			{
				iStar = i;
				jStar = j++;
			}//If the match is unsuccessful after '*', iStar moves backward and j resets to the next character of '*'
			else if (iStar >= 0)
			{
				i = ++iStar;
				j = jStar + 1;
			}//false in all other cases
			else return false;
		}
		//If there is "*" after j, delete it
		while (j < n && p[j] == '*') ++j;
		
		return j == n;
	}
};
int main()
{
	Solution solution;
	string num1 = "adceb";
	string num2 = "*a*b";

	if (solution.isMatch(num1, num2))
		cout << "yes" << endl;
	else
		cout << "no" << endl;

	system("pause");
	return 0;
}

 

Posted by chris.zeman on Sat, 20 Jun 2020 01:15:31 -0700