解法一:遞歸spa
剛開始簡單地覺得掃描字符串,而後對比就好了。但因爲有「*」,沒法考慮全部狀況。所以這題使用了遞歸的方法來解,即不斷地縮短字符串長度,直到分解爲最基礎的幾種狀況。因爲」*"表示重複任意次數,所以應該有一個回溯的過程。固然重複次數最大是帶匹配的字符串的的長度。code
難度在於基礎狀況的處理以及如何遞歸。基礎狀況須要仔細考慮纔不會遺漏。好比s爲空,p爲空等。代碼以下:blog
class Solution { public: bool isMatch(const char *s, const char *p) { const char *s_pos=s; const char * p_pos=p; if(*s!='\0'&&*p=='\0') return false; if(*s=='\0'&&*p=='\0') return true; if(*s=='\0'&&*p!='\0') { if(*(p+1)=='*') return isMatch(s,p+2); return false; } if(*(p+1)!='*') return ((*s==*p)||(*p=='.'))&&isMatch(s+1,p+1); else { //caculate the max num of repeating a char int c=0; while(*(s+c)!='\0') c++; bool m=true; for(int i=0;i<=c;i++) { //cout<<"i: "<<i<<endl; m=true; for(int j=0;j<i;j++) { bool t=((*(s+j)==*p)||(*p=='.')); //cout<<"i: "<<i<<" j: "<<j<<" "<<t<<endl; if(t==false) { m=false; continue; } } if(m==false) break; else { //cout<<"enter next: "<<i<<endl; m=m&&isMatch(s+i,p+2); if(m==true) return true; } } } return false; } };
解法二:動態規劃法遞歸
dp的方法是第二遍回頭作的時候寫的。此時明顯感到思路比之前清晰了不少。。。再次強調,dp最關鍵的是要搞清楚matrix的意義。就此題而言,很是清楚:dp[i][j]表示S的前i個字符與P的前j個字符匹配。字符串
更新規則:分類考慮,包括p[j]是普通字符,‘.'字符以及'*'字符。前二者更新規則比較清晰;‘*’字符比較麻煩,要分爲重複0次以及重複0次以上。代碼以下:io
public class Solution { public boolean isMatch(String s, String p) { if(s==null||p==null) return false; int m=s.length()+1; int n=p.length()+1; boolean dp[][]=new boolean[m][n]; dp[0][0]=true; for(int i=1;i<n;i++) { if(p.charAt(i-1)=='*') { if(dp[0][i-2]||dp[0][i-1]) dp[0][i]=true; } } for(int i=1;i<m;i++) { for(int j=1;j<n;j++) { char sc=s.charAt(i-1); char pc=p.charAt(j-1); if(pc=='.'||sc==pc) { dp[i][j]=dp[i-1][j-1]?true:false; } else if(pc=='*') { char pre=p.charAt(j-2); if(dp[i][j-2]) { //repeat zero time dp[i][j]=true; continue; } if((pre=='.'||pre==sc)&&dp[i-1][j]) { //repeat at least one time dp[i][j]=true; continue; } } } } return dp[m-1][n-1]; } }
上述代碼中,重複0次和重複屢次的條件分開寫實爲了思路更清晰。由於重複0次是以行爲參考,重複屢次是以列爲參考。ast
網上彷佛有人說用動態規劃方法。DP一直是隻知其一;不知其二,之後考慮再用DP解。class