详细见:leetcode.com/problems/regular-expression-matching/
说明: 回溯版本好理解,DP版本解释如下:
建立行len(s)+1和列len(p)+1的dp矩阵
dp[i+1][j+1]代表s[0,i]和p[0,j]的匹配结果。
有两种匹配上情况:
1,字符相同或者p是'.'
2,p是'*',有匹配0次,匹配1次,匹配多次三种情况
Java Solution: github
package leetcode;
import java.util.ArrayList;
public class P010_RegularExpressionMatching {
/*
* 33.84%
* 97ms
*/
static class Solution2 {
public boolean isMatch(String s, String p) {
if (s == null)
return p == null;
if (p == null)
return s == null;
return isMatch(s, 0, s.length(), p, 0, p.length());
}
private boolean isMatch(String s, int i, int I, String p, int j, int J) {
if (getChar(p, j, J) == '\0') return getChar(s, i, I) == '\0';
if (getChar(p, j + 1, J) == '*') {
while (getChar(s, i, I) == getChar(p, j, J) || (getChar(p, j, J) == '.' && getChar(s, i, I) != '\0')) {
if (isMatch(s, i ++, I, p, j + 2, J))
return true;
}
return isMatch(s, i, I, p, j + 2, J);
} else {
if (getChar(s, i, I) == getChar(p, j, J) || (getChar(p, j, J) == '.' && getChar(s, i, I) != '\0'))
return isMatch(s, i + 1, I, p, j + 1, J);
return false;
}
}
private char getChar(String str, int i, int I) {
if (i >= I)
return '\0';
else
return str.charAt(i);
}
}
static class Solution8 {
public boolean isMatch(String s, String p) {
if (s == null) return p == null;
int sn = s.length(), pn = p.length();
boolean[][] m = new boolean[sn + 1][pn + 1];
m[0][0] = true;
for (int pi = 0; pi < pn; pi ++)
if (p.charAt(pi) == '*' && m[0][pi - 1])
m[0][pi + 1] = true;
for (int si = 0; si < sn; si ++) {
for (int pi = 0; pi < pn; pi ++) {
char sc = s.charAt(si), pc = p.charAt(pi);
if (sc == pc || '.' == pc) {
m[si + 1][pi + 1] = m[si][pi]; //匹配1次
} else if (pc == '*' ) {
//[pi-1, pi]结成共同体
if (sc == p.charAt(pi - 1) || '.' == p.charAt(pi - 1)) {
5 m[si + 1][pi + 1] =
m[si][pi + 1] || //匹配很多次 s[si]和{p[pi-1], p[pi]}已经匹配上
//肯定s[0,si-1]还要和p[0,pi]去匹配嘛
m[si + 1][pi - 1] || //匹配0次 按照道理应该是s[0,si]和p[0,pi-2]去匹配
m[si][pi - 1]; //匹配1次 s[si]和{p[pi-1], p[pi]}匹配上
//就是看,s[0,si-1]和p[0,pi-2]是否能够匹配上
} else {
m[si + 1][pi + 1] = m[si + 1][pi - 1]; //只能匹配0次
}
} else {
m[si + 1][pi + 1] = false;
}
}
}
return m[sn][pn];
}
}
}
C Solution: github
/*
url: leetcode.com/problems/regular-expression-matching/
_match: 64ms 6.40%
_match_dp: 9ms 83.74%
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define bool int
#define true 1
#define false 0
char _access_char_array(char *s, int sn, int i) {
if (i >= sn) return '\0';
return *(s + i);
}
bool _judge(char sc, char pc) {
return sc == pc || (pc == '.' && sc != '\0');
}
//use trace back
bool _match(char* s, int sn, int si, char* p, int pn, int pi) {
char sc = _access_char_array(s, sn, si);
char pc = _access_char_array(p, pn, pi);
if (pc == '\0') return sc == '\0';
if (_access_char_array(p, pn, pi + 1) == '*') {
while (_judge(sc, pc)) {
if (_match(s, sn, si, p, pn, pi + 2))
return 1;
sc = _access_char_array(s, sn, ++ si);
}
return _match(s, sn, si, p, pn, pi + 2);
}
return _judge(sc, pc) && _match(s, sn, si + 1, p, pn, pi + 1);
}
//use dp
bool _match_dp(char* s, char* p) {
int sn = strlen(s), pn = strlen(p);
int si = 0, pi = 0;
int sic = 0;
char sc = '\0', pc = '\0';
char ** dp = (char **) malloc(sizeof(char *) * (sn + 1));
for (si = 0; si < sn + 1; si ++)
* (dp + si) = (char *) malloc(sizeof(char) * (pn + 1));
for (si = 0; si < sn + 1; si ++) //set default 0
memset(*(dp + si), 0, pn + 1); //diff with java
**dp = 1; //""(p) match ""(s)
for (si = 0, pi = 0; pi < pn; pi ++) {
if (*(p + pi) == '*' && *(*(dp + si) + pi - 1)) {
*(*(dp + si) + pi + 1) = 1; //how p match ""(s)
}
}
for (si = 0; si < sn; si ++) {
for (pi = 0; pi < pn; pi ++) {
if (*(s + si) == *(p + pi) || *(p + pi) == '.') {
*(*(dp + si + 1) + pi + 1) = *(*(dp + si) + pi);
} else if (*(p + pi) == '*') {
if (*(p + pi - 1) != *(s + si) && *(p + pi - 1) != '.') //only use zero
*(*(dp + si + 1) + pi + 1) = *(*(dp + si + 1) + pi - 1);
else
*(*(dp + si + 1) + pi + 1) =
*(*(dp + si) + pi + 1) || //* use many times
*(*(dp + si + 1) + pi) || //* use zero times
*(*(dp + si + 1) + pi - 1); //* use one time
} else {
*(*(dp + si + 1) + pi + 1) = 0; //p[0,pi] can not match s[0,si]
}
}
}
//ans
sic = *(*(dp + sn) + pn);
for (si = 0; si < sn + 1; si ++)
free(*(dp + si));
free(dp);
return sic;
}
bool isMatch(char* s, char* p) {
if (s == NULL || p == NULL) return s == NULL && p == NULL;
return _match(s, strlen(s), 0, p, strlen(p), 0);
}
int main() {
char *s = "aa";
char *p = "aa";
printf("answer is %d\r\n", isMatch(s, p));
printf("dp answer is %d\r\n", _match_dp(s, p));
return 0;
}
#coding=utf-8
'''
url: leetcode.com/problems/regular-expression-matching/
@author: zxwtry
@email: zxwtry@qq.com
@date: 2017年3月27日
@details: BackTraceSolution: TLE
@details: DPSolution: AC 99ms 67.25%
'''
class DPSolution(object):
def isMatch(self, s, p):
I = 0 if s == None else len(s)
J = 0 if p == None else len(p)
m = [[False for i in range(J + 1)] for j in range(I + 1)]
m[0][0] = True
for j in range(J):
if '*' == p[j] and m[0][j - 1]:
m[0][j + 1] = True
for i in range(I):
for j in range(J):
if s[i] == p[j] or '.' == p[j]:
m[i + 1][j + 1] = m[i][j]
elif p[j] == '*':
if s[i] != p[j - 1] and '.' != p[j - 1]:
m[i + 1][j + 1] = m[i + 1][j - 1]
else:
m[i + 1][j + 1] = \
m[i][j + 1] or\
m[i][j - 1] or\
m[i + 1][j - 1]
#[p[j - 1],p[j]]组成一组
#匹配多次,看s[0,i-1]和p[0,j]是否能够匹配
#匹配一次,看s[0,i-1]和p[0,j-2]是否能够匹配
#匹配0次,看s[0,i]和p[0,j-2]是否能够匹配
else:
m[i + 1][j + 1] = False
return m[I][J]
class BackTraceSolution(object):
def a(self, s, i, l):
return s[i] if i < l else '\0'
def m(self, s, i, I, p, j, J):
sc, pc = self.a(s, i, I), self.a(p, j, J)
if pc == '\0': return sc == '\0'
if self.a(p, j + 1, J) == '*':
while sc == pc or (pc == '.'and sc != '\0'):
i += 1
sc = self.a(s, i, I)
if self.m(s, i - 1, I, p, j + 2, J):
return True
return self.m(s, i, I, p, j + 2, J)
else:
if sc == pc or (pc == '.' and sc != '\0'):
return self.m(s, i + 1, I, p, j + 1, J)
return False
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
I = 0 if s == None else len(s)
J = 0 if p == None else len(p)
return self.m(s, 0, I, p, 0, J)
if __name__ == "__main__":
s = "baccbbcbcacacbbc"
p = "c*.*b*c*ba*b*b*.a*"
print(DPSolution().isMatch(s, p))