解法一:递归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