【leetcode】44. (Medium) WildCard Matching
解題思路:
這道題的意思就是字串匹配,s是正常的字串,p是帶有特殊字元的字串,在p中,’?‘可以匹配任意一個字元,’*'可以匹配任意長度(包括0)的字元。
這道題可以用DP來做。(初始答案在題目後面的Description裡)
首先動態規劃的特點是會求得所有過程中的結果。
具體做法:
設s=adceb p=* a* b 我們先建立一個boolean二維陣列match,行數為s.length+1,用於存放s字串;寬為p.length+1,用於存放p字串;
陣列中任意一個value的值表示的是當前行及以下的s和當前列及以後的p的字串是否匹配,如果兩個方框所示。所以這裡DP的方法是從尾匹配到頭
現在說明匹配過程:
首先match[s.length][p.length]=true
然後對於最後一排,滿足:
if(p.charAt(i)==’*’)
match[s.length()][i]=true;
就是最後一排,從後到前開始算,遇到p字串的內容是’*'的話,值是true,這裡p字串的後面沒有 ’ * ',所以最後一排的其他數值不做處理,直接跳到倒數第二行。
對於剩下的部分,只對中間部分進行計算,最後一列不做處理:
對於中間部分處理的順序是,從最後一排的尾處理到頭、從倒數第二排的尾處理到頭、…
對於這些內容,處理的規則是:
if(s.charAt(i)==p.charAt(j)||p.charAt(j)=='?') match[i][j]=match[i+1][j+1]; else if(p.charAt(j)=='*') match[i][j]=match[i+1][j]||match[i][j+1]; else match[i][j]=false;
即分為三種情況,第一種:s[i]和p[j]字元是相同的
此時3處的數值match[i][j]取決於右下方的數值match[i+1][j+1]:
第二種,p[j]==’*’:
此時只要match[i][j]的右邊是true或者下邊是true,自己就是true:
第三種情況,s[i]!=p[j]:
直接false
根據這個規則可以填滿所有的地方:
* | a | * | b | - | |
---|---|---|---|---|---|
a | true | true | true | false | |
d | false | false | true | false | |
c | false | false | true | false | |
e | false | false | true | false | |
b | false | false | true | true | |
- | true |
同時,match[0][0]就是最終的答案:
這個過程其實將所有過程中的答案都給了出來,符合DP的特點,比如下圖中:
這個值的意思是" c e b “和” * b "字串是匹配的
這個值表示"dceb"和"* a* b"是不匹配的
提交程式碼:
class Solution{
public boolean isMatch(String s, String p) {
boolean match[][]=new boolean[s.length()+1][p.length()+1];
match[s.length()][p.length()]=true;
for(int i=p.length()-1;i>=0;i--) {
if(p.charAt(i)=='*')
match[s.length()][i]=true;
else break;
}
for(int i=s.length()-1;i>=0;i--) {
for(int j=p.length()-1;j>=0;j--) {
if(s.charAt(i)==p.charAt(j)||p.charAt(j)=='?')
match[i][j]=match[i+1][j+1];
else if(p.charAt(j)=='*')
match[i][j]=match[i+1][j]||match[i][j+1];
else
match[i][j]=false;
}
}
return match[0][0];
}
}
執行結果: