LeeCode (dynamic rules, greedy algorithm) 44_ wildcard matching

LeeCode (dynamic rules, greedy algorithm) 44_ wildcard matching

Topic:
Given a string(s) and a character pattern§, implement a wildcard matching that supports'?' and'*'.

'?' can match any single character.
'*' can match any string (including empty strings).
Only when two strings match exactly is the match successful.

Description:

s may be empty and only contain lowercase letters from az.
p may be empty and only contain lowercase letters from az, 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

Source: LeetCode
Link: https://leetcode-cn.com/problems/wildcard-matching
Copyright is owned by LeetCode . For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Problem-solving ideas:

Method one:
dynamic programming

  1. Create a dp[][] to save all matching conditions, and use dp[i][j] to indicate whether the first i characters of s and the first j characters of p match.
  2. The matching situation is roughly divided into three types:
    1. si=pi
    2. pi is the number
    3. pi is the * number

The state transition equation after integration:

State transition equation after integration

Determine the boundary:

  • dp[0][0]=True, that is, when the string s and the pattern p are both empty, the match is successful;

  • dp[i][0]=False, that is, an empty pattern cannot match a non-empty string;

  • dp[0][j] needs to be discussed separately: because the asterisk can match the empty string, dp[0][j] is true only when the first j characters of the pattern p are all asterisks.

Java code:

public class 通配符匹配 {
    
    

	public boolean isMatch(String s,String p){
    
    
		int m = s.length();
		int n = p.length();
		boolean[][] dp = new boolean[m+1][n+1];
		dp[0][0] =true;
		for(int i=1;i<=n;i++){
    
    
			if(p.charAt(i-1)=='*'){
    
    
				dp[0][i]=true;
			}else{
    
    
				break;
			}
		}
		for(int i=1;i<=m;i++){
    
    
			for(int j=1;j<=n;j++){
    
    
				if(p.charAt(j-1)=='*'){
    
    
					dp[i][j]=dp[i-1][j] || dp[i][j-1];
				}else if(p.charAt(j-1)=='?' || p.charAt(j-1)==s.charAt(i-1)){
    
    
					dp[i][j] = dp[i - 1][j - 1];
				}
			}
		}
		return dp[m][n];
	}
}

Method 2:
Greedy Algorithm

  1. Because it can match one or more characters, all n and 1 * are actually equivalent. So we can regard p as p=∗ u1∗u2∗u3∗u4∗u5∗u6∗

  2. The essence of the algorithm is to first find u1 in s and then find u2, u3...

In addition, there are two situations:

  • The beginning character of pattern p is not an asterisk;
  • The ending character of pattern p is not an asterisk.

The second case is not complicated to deal with. If the end character of the pattern p is not an asterisk, then it must match the end character of the string s. Then we keep matching the ending characters of s and p until p is empty or the ending character of p is an asterisk. In this process, if the match fails, or finally p is empty but s is not empty, then False needs to be returned.

The handling of the first case is similar, we can continuously match the beginning characters of s and p. Another processing method is given in the following code, which is to modify the initial value of sRecord and tRecord to −1, which means that the beginning character of the pattern p is not an asterisk, and it is judged when the match fails, if their value is still − 1. It means that there is no chance to "return" the match again.

Java code:

public class 通配符匹配 {
    
    

    public boolean isMatch(String s, String p) {
    
    
    	int sRight = s.length();
    	int pRight = p.length();
    	//不是以*号结尾
    	while(sRight>0 && pRight>0 && p.charAt(pRight-1)!='*'){
    
    
    		if(charMatch(s.charAt(sRight-1),p.charAt(pRight-1))){
    
    
    			--sRight;
    			--pRight;
    		}else{
    
    
    			return false;
    		}
    	}
    	
    	if(pRight==0){
    
    
    		return sRight==0;
    	}
    	
    	int sIndex=0,pIndex=0;
    	int sRecord=-1,pRecord=-1;
    	
    	while(sIndex<sRight && pIndex<pRight){
    
    
    		if(p.charAt(pIndex)=='*'){
    
    
    			++pIndex;
    			sRecord=sIndex;
    			pRecord=pIndex;
    		}else if(charMatch(s.charAt(sIndex),p.charAt(pIndex))){
    
    
    			++pIndex;
    			++sIndex;
    		}else if(sRecord!=-1 && sRecord+1 < sRight){
    
    
    			++sRecord;
    			sIndex = sRecord;
                pIndex = pRecord;
    		}else{
    
    
    			return false;
    		}
    	}
    	return allStars(p,pIndex,pRight);
    }

    public boolean allStars(String str, int left, int right) {
    
    
       for(int i=left;i<right;i++){
    
    
    	   if(str.charAt(i)!='*'){
    
    
    		   return false;
    	   }
       }
       return true;
    }

    public boolean charMatch(char u, char v) {
    
    
        return u==v || u=='?';
    }

}

Guess you like

Origin blog.csdn.net/u013456390/article/details/111865076