您的位置:首页 > 其它

LeetCode 10 Regular Expression Matching

2016-11-03 14:59 344 查看
Implement regular expression matching with support for 
'.'
 and 
'*'
.
'.' Matches any single character.
'*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true


说明:*号之前的字符可以出现多次,比如说a*b可以和ab也可以和aab匹配,甚至也可以和b匹配,因为a可以出现0次。

思路:设定i,j作为两个游标,分别指向s[i],p[j],dp[i][j]代表s[i]和p[j]是否匹配
 以及 i,j之后的字符是否已经匹配。

这里重点讲解 j + 1 < pn && p[j + 1] == '*'
的情况。因为p[j + 1] == '*' ,而'*' 可以代表0个或者多个p[j] 。

如果'*' 代表0个p[j],那么,我们就无视p[j],同时由于p[j+1]=='*',因此p[j+1]也要一起被我们无视了,因此p的游标
j 忽略p[j+1],p[j]两位,依然指向p[j+2],s的游标 i
不动,依然指向 s[i],于是我们比较
p[j+2]和s[i]是否相等即可,即dp[i][j+2]。例:我们看s= cb和 p = ca*b是否匹配,因为*可以当作0个a,所以是匹配的,这个时候当游标
j 指向p[1]='a'的时候,由于p[2]='*'因此我们就直接判断p[3]是否等于s[1]即可。

如果'*' 代表1个或者多个p[j],那么,如果s[i]
== p[j],dp[i][j]的值就依赖于dp[i+1][j],因为p[j+1]=='*',因此p[j]可以循环利用。例如s =  caaaab、p
= ca*b,当游标 j
指向p[1]='a'的时候,由于p[2]='*',此时如果游标 i 指向s[4]='a'=p[1],只要dp[5][1] ==dp[5][3] =true,因此dp[4][1]也为ture;如果 i
指向s[3]=='a'=p[1],只要dp[4][1]为ture……

Runtime: 32
ms beats 61.31% of java submissions. dp解法效率上比起动辄上百毫秒的递归好很多了。

public boolean isMatch(String ss, String pp) {
int pn = pp.length(), sn = ss.length();
boolean[][] dp = new boolean[sn + 1][pn + 1];
char[] s = ss.toCharArray(), p = pp.toCharArray();
dp[sn][pn] = true;
for (int i = sn; i >= 0; i--)
for (int j = pn - 1; j >= 0; j--)
if (j + 1 < pn && p[j + 1] == '*')
dp[i][j] = dp[i][j + 2] ||
i < sn && (p[j] == '.' || s[i] == p[j]) && dp[i + 1][j];
else dp[i][j] = i < sn && (p[j] == '.' || s[i] == p[j]) && dp[i + 1][j + 1];
return dp[0][0];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: