转载 http://www.cnblogs.com/yuzhangcmu/p/4105529.html
LeetCode: Regular Expression Matching 解题报告
Regular Expression Matching
Question
Solution
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
Hide Tags Dynamic Programming Backtracking String
SOLUTION1:
总的来说思路是递归。
判断下一个字符是否是*:
如果不是*,则判断当前字符是否匹配。
如果是*,则因为不能确定*到底会匹配几个,在当前字符匹配的前提下,要枚举所有的情况,从假设匹配0个,1个,2个。。。只要有一种情况成功了,最终也就成功了。
我们可以从0开始,先考虑直接跳过当前2个正则字符,然后再1个,2个继续搜索下去。
如果是*,但是当前字符不匹配,则跳过两个递归。
具体的代码如下,注释写得很清楚。
ref: http://blog.csdn.net/fightforyourdream/article/details/17717873
SOLUTION2:
稍微重写了一下,思路没有什么大的变化,但是简化了一点点:
我们只需要判断2种情况:
1. 下一个是*的情况,这个时候不需要考虑S长度。因为S为空也是可以的。
2. 下一个不是*,这个统一考虑,当前s必须留下至少一个字符,如果有,继续递归即可。
2014.12.28 Redo:
时间复杂度: 2^N
因为,假设P全是a*a*a*这样组成,s = aaaaaaaa 而s的每一个字符都有2种可能:与当前的a*匹配,或者与下一个a*匹配(前一个匹配空),这样假设
s有n个字符,则实际上的复杂度是2^N.
从下是RUNTIME:
SOLUTION3:
记忆化搜索,在SOLUTION 2的基础上,加上记忆矩阵。复杂度为M*N*M。
最后一个m是遇到*时,需要遍历一次string。
SOLUTION 4:
DP:
D[i][j]: 表示string s中取i长度的字串,string p中取j长度字串,进行匹配。
状态转移:
1. j >= 2 && P[j - 1] = *,这时,我们可以选择匹配s中的空字串,或匹配无限个。
k: 在s中匹配的字符的个数
所以转移式是:D[i][j] = D[i - k][j - 2] && isSame(s.charAt(i - k), p.charAt(j - 2)) (k: 1-i)
D[i - k][j - 2] (k = 0)
2. p最后一个字符不是*
那么首先,s中至少还要有一个字符,然后再匹配一个字符,以及上一级也要匹配即可。
D[i][j] = i >= 1
&& isSame(s.charAt(i - 1), p.charAt(j - 1))
&& D[i - 1][j - 1];
3. j = 0;
D[i][j] = i == 0; (p为空,则s也是要为空才可以匹配)
以下是运行时间(LEETCODE这道题目的数据太弱了... orz),看不出太大的区别。
GitHub:
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/string/isMatch.java
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/string/isMatch_2014_1228.java