LeeCode(動的ルール、欲張りアルゴリズム)44_ワイルドカードマッチング

LeeCode(動的ルール、欲張りアルゴリズム)44_ワイルドカードマッチング

トピック:
文字列と文字パターン§が与えられた場合、「?」と「*」をサポートするワイルドカードマッチングを実装します。

「?」は任意の1文字に一致します。
「*」は任意の文字列(空の文字列を含む)に一致できます。
2つの文字列が完全に一致する場合にのみ、一致が成功します。

説明:

sは空で、azからの小文字のみを含めることができます。
pは空で、azの小文字と文字?および*のみを含めることができます。
例1:

入力:
s = "aa"
p = "a"
出力:false
説明: "a"は "aa"のストリング全体と一致できません。
例2:

入力:
s = "aa"
p = " "
出力:true
説明: '
'は任意の文字列に一致します。
例3:

入力:
s =“ cb”
p =“?a”
出力:false
説明:「?」は「c」と一致できますが、2番目の「a」は「b」と一致できません。
例4:

入力:
s = "adceb"
p = " a b"
出力:true
説明:最初の ' 'は空の文字列と一致し、2番目の ' 'は文字列 "dce"と一致します。
例5:

入力:
s =“ acdcb”
p =“ a * c?b”
出力:false

出典:LeetCode(LeetCode)
リンク:https ://leetcode-cn.com/problems/wildcard-matching
著作権はLeetCodeが所有しています商用の再版については、公式の承認に連絡してください。非商用の再版については、出典を示してください。

問題解決のアイデア:

方法1:
動的計画

  1. dp [] []を作成してすべての一致条件を保存し、dp [i] [j]を使用して、sの最初のi文字とpの最初のj文字が一致するかどうかを示します。
  2. マッチング状況は大きく3つのタイプに分けられます:
    1。si= pi 2.pi
    は数字です3.pi
    は*数字です

積分後の状態遷移方程式:

積分後の状態遷移方程式

境界を決定します。

  • dp [0] [0] = True、つまり、文字列sとパターンpの両方が空の場合、一致は成功します。

  • dp [i] [0] = False、つまり、空のパターンは空でない文字列と一致できません。

  • dp [0] [j]については、個別に説明する必要があります。アスタリスクは空の文字列と一致する可能性があるため、dp [0] [j]は、パターンpの最初のj文字がすべてアスタリスクである場合にのみ真になります。

Javaコード:

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];
	}
}

方法2:
欲張りアルゴリズム

  1. 1つ以上の文字に一致する可能性があるため、すべてのnと1 *は実際には同等です。したがって、pはp = ∗ u1 ∗ u2 ∗ u3 ∗ u4 ∗ u5 ∗ u6 ∗と見なすことができます。

  2. アルゴリズムの本質は、最初にsでu1を見つけ、次にu2、u3 ...を見つけることです。

さらに、2つの状況があります。

  • パターンpの最初の文字はアスタリスクではありません。
  • パターンpの終了文字はアスタリスクではありません。

2番目のケースは扱いが複雑ではありません。パターンpの終了文字がアスタリスクでない場合は、文字列sの終了文字と一致する必要があります。次に、pが空になるか、pの終了文字がアスタリスクになるまで、sとpの終了文字を一致させ続けます。このプロセスで、一致が失敗した場合、または最終的にpが空であるが、sが空でない場合は、Falseを返す必要があります。

最初のケースの処理は同様であり、sとpの開始文字を継続的に一致させることができます。次のコードでは、sRecordとtRecordの初期値を-1に変更する別の処理方法を示しています。これは、パターンpの開始文字がアスタリスクではなく、一致が失敗した場合に判断されることを意味します。それらの値はまだ-1です。これは、一致を再照合する機会がないことを示しています。

Javaコード:

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=='?';
    }

}

おすすめ

転載: blog.csdn.net/u013456390/article/details/111865076