LeetCode Regular Expression Matching

来源:互联网 发布:mac双系统卸载苹果系统 编辑:程序博客网 时间:2024/04/27 22:23

这题没那么简单,贪心不行。自己写的递归,改了几次终于通过。

bool isMatch(const char *s, const char *p){if(s==NULL||p==NULL) return false;if(*s==0&&*p==0) return true;else{if(*s==0&&*p!=0){const char *q=p;while(*q){if(*(q+1)!='*') return false;q+=2;}return true;}else{if(*s!=0&&*p==0){const char *q=s;while(*q){if(*(q+1)!='*') return false;q+=2;}return true;}else{if(*(s+1)!='*'&&*(p+1)!='*'){if(*s==*p)return isMatch(s+1,p+1);else{if(*s=='.'||*p=='.')return isMatch(s+1,p+1);elsereturn false;}}else{if(*(s+1)=='*'&&*(p+1)!='*'){bool flag=false;const char *q=p;if (*s=='.'){while(*q){//if((*q!=*s)&&(*s!='.')&&(*p!='.')) return false;flag = isMatch(s+2,q);q++;if(*q=='*')q++;if(flag==true) return true;}return isMatch(s+2,q);}else{while (*q&&*q==*s){flag = isMatch(s+2,q);q++;if(*q=='*')q++;if(flag==true) return true;}return isMatch(s+2,q);}}else{if(*(s+1)=='*'&&*(p+1)=='*'){return isMatch(s+2,p)||isMatch(s,p+2)||isMatch(s+2,p+2);}else{bool flag=false;const char *q=s;if (*p=='.'){while(*q){//if(*q!=*p&&*p!='.'&&*s!='.') return false;flag = isMatch(q,p+2);q++;if(*q=='*')q++;if(flag==true) return true;}return isMatch(q,p+2);}else{while (*q&&*q==*p){flag = isMatch(q,p+2);q++;if(*q=='*')q++;if(flag==true) return true;}return isMatch(q,p+2);}}}}}}}}
后来看别人的递归程序,简单干练。递归如下:

bool isMatch(const char *s, const char *p) {assert(s && p);if (*p == '\0') return *s == '\0';// next char is not '*': must match current characterif (*(p+1) != '*') {assert(*p != '*');return ((*p == *s) || (*p == '.' && *s != '\0')) && isMatch(s+1, p+1);}// next char is '*'while ((*p == *s) || (*p == '.' && *s != '\0')) {if (isMatch(s, p+2)) return true;s++;}return isMatch(s, p+2);}
再看看速度更快的DP吧,看了一晚上,终于看懂了,还没看的太懂。动态规划如下:

bool isMatch(const char *s, const char *p) {  int slen = strlen(s), plen = strlen(p), i, j;  bool dp[500][500];  memset(dp,false, sizeof(dp));  dp[0][0] = true;  for (i = 1; i <= plen; ++i) {  if (p[i] == '*') {  dp[i][0] = dp[i + 1][0] = dp[i - 1][0];  for (j = 1; j <= slen; ++j)  dp[i][j] = dp[i + 1][j] = (dp[i][j - 1] && (p[i - 1] == s[j - 1] || p[i - 1] == '.') || dp[i - 1][j]);  ++i;          }  else  for (j = 1; j <= slen; ++j)  dp[i][j] = dp[i - 1][j - 1] && (p[i - 1] == s[j - 1] || p[i - 1] == '.');  }  return dp[plen][slen];  }
上面这个我是略微看懂了,不知道怎么说出来,可以拿例子试试p为ac*a*b,s为aab。还有一个DP的程序没怎么看懂,如下,其中用容器的容器来表示二维数组到可以学学:

bool isMatch(const char *s, const char *p) {  // Start typing your C/C++ solution below  // DO NOT write int main() function      if ( !s || !p )  return !s&&!p;  int ns=strlen(s);  int np=strlen(p);  vector<vector<bool> > dp(ns+1,vector<bool>(np+1,0));  dp[0][0]=true;  for(int i=1;i<=ns;i++)  {  if ( s[i-1]=='*' )  {  assert(i>=2);  dp[i][0]=dp[i-2][0];  }  }  for(int j=1;j<=np;j++)  {  if ( p[j-1]=='*' )  {  assert(j>=2);  dp[0][j]=dp[0][j-2];  }  }  for(int i=1;i<=ns;i++)  {  for(int j=1;j<=np;j++)  {  if (s[i-1]=='.'||p[j-1]=='.')  dp[i][j]=dp[i-1][j-1];  else if ( s[i-1]=='*')  dp[i][j]=dp[i-1][j]||dp[i-2][j];  else if ( p[j-1]=='*')  dp[i][j]=dp[i][j-1]||dp[i][j-2]||(dp[i-1][j]&&(s[i-1]==p[j-2]||p[j-2]=='.'));  else  dp[i][j]=dp[i-1][j-1]&&s[i-1]==p[j-1];  }  }  return dp[ns][np];  } 
小说明:上面的三个算法都只考虑了只有一个输入有*的情况,对于aab,c*a*b这样的测试用例,返回真,但是反过来c*a*b,aab就返回假。但是LeetCode编译仍能通过。我的程序虽然看起来不整洁却能对上面的测试用例返回正确的值。