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:
動的計画法
- dp [] []を作成してすべての一致条件を保存し、dp [i] [j]を使用して、sの最初のi文字とpの最初のj文字が一致するかどうかを示します。
- マッチング状況は大きく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つ以上の文字に一致する可能性があるため、すべてのnと1 *は実際には同等です。したがって、pはp = ∗ u1 ∗ u2 ∗ u3 ∗ u4 ∗ u5 ∗ u6 ∗と見なすことができます。
-
アルゴリズムの本質は、最初に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=='?';
}
}