leetcode 10-Regular Expression Matching(hard)
Posted yshi12
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 10-Regular Expression Matching(hard)相关的知识,希望对你有一定的参考价值。
Given an input string (s
) and a pattern (p
), 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).
Note:
s
could be empty and contains only lowercase lettersa-z
.p
could be empty and contains only lowercase lettersa-z
, and characters like.
or*.
cases:
two pointers, one for s (sp), one for p (pp)
1. p[pp] is letter:
(1)p[pp+1]!=‘*‘, s[sp]!=p[pp] return false;
(2)p[pp+1]=‘*‘, ‘*‘ means zero all more p[pp], we can jump p[pp] and p[pp+1] or iterate through all continuous and equals p[pp] in s, and continue matching
2. p[pp]=‘.‘:
(1)p[pp+1]!=‘*‘: sp++,pp++;
(2)p[pp+1]==‘*‘: sp can iterate through all the following letters in s to see whether there is a match.
3. p[pp]=‘*‘ return false;
注意 在iterate的时候,在用while的时候一定要记得写循环变量的变化,不要以为是for循环会自己加一,要不然会陷入死循环!
class Solution { public boolean isMatch(String s, String p) { if(s.length()==0 && p.length()==0) return true; else if(p.length()==0) return false; return findMatch(s, p, 0, 0); } public boolean findMatch(String s, String p, int sp, int pp){ if(sp==s.length()&&pp==p.length()) return true; else if(pp==p.length()) return false; if(p.charAt(pp)!=‘*‘&&p.charAt(pp)!=‘.‘){ if(pp==p.length()-1||p.charAt(pp+1)!=‘*‘){ if(sp==s.length()||s.charAt(sp)!=p.charAt(pp)) return false; return findMatch(s, p, sp+1, pp+1); } else{ if(findMatch(s,p,sp,pp+2)) return true; while(sp<s.length()&&s.charAt(sp)==p.charAt(pp)){ if(findMatch(s,p,sp+1,pp+2)) return true; sp++; } return false; } } else if(p.charAt(pp)==‘.‘){ if(sp==s.length()&&(pp<p.length()-1&&p.charAt(pp+1)!=‘*‘)) return false; if(pp==p.length()-1||p.charAt(pp+1)!=‘*‘) return findMatch(s, p, sp+1,pp+1); else{ while(sp<=s.length()){ if(findMatch(s,p,sp,pp+2)) return true; sp++; } return false; } } else return false; } }
以上为自己瞎折腾改了半天的代码,需要考虑的情况太多,逻辑在细节和corner case处比较乱,反面教材!
以下参考leetcode大神代码:
https://leetcode.com/problems/regular-expression-matching/discuss/5651/Easy-DP-Java-Solution-with-detailed-Explanation
DP:
string s, i
string p, j
2D dp array
1. s.charAt(i)==p.charAt(j): dp[i][j]=dp[i-1][j-1]
2. p.charAt(j)==‘.‘: dp[i][j]=dp[i-1][j-1]
3. p.charAt(j)==‘*‘:
two cases:(1)s.charAt(i)!=p.charAt(j-1): dp[i][j]=dp[i][j-2]
(2)s.charAt(i)==p.charAt(j-1): dp[i][j]=dp[i][j-2] //in this case, a* counts as empty
or dp[i][j]=dp[i][j-1] //in this case, a* counts as single a
or dp[i][j]=dp[i-1][j] //in this case, a* counts as multiple a
class Solution { public boolean isMatch(String s, String p) { if(s==null||p==null) return false; boolean[][] dp=new boolean[s.length()+1][p.length()+1]; dp[0][0]=true; for(int j=1;j<dp[0].length;j++){ if(j>1&&p.charAt(j-1)==‘*‘) dp[0][j]=dp[0][j-2]; } for(int i=1;i<dp.length;i++){ for(int j=1;j<dp[0].length;j++){ if(s.charAt(i-1)==p.charAt(j-1) || p.charAt(j-1)==‘.‘) dp[i][j]=dp[i-1][j-1]; else if(p.charAt(j-1)==‘*‘){ if(j>1){ if(s.charAt(i-1)==p.charAt(j-2)||p.charAt(j-2)==‘.‘){ dp[i][j]=dp[i][j-2]||dp[i][j-1]||dp[i-1][j]; } else{ dp[i][j]=dp[i][j-2]; } } } } } return dp[s.length()][p.length()]; } }
非常简洁明晰,dp的时候首先注意初始化(0,0)的情况,然后考虑分别为0的情况的初始化,一定要注意的是,dp矩阵的长宽都是比string的长度大1的,在写的时候,dp[i][j],对于相应的string中,下标一定不要忘记是i-1,j-1之类。
部分细节处做了修改:虽然leetcode测试case没有 s="", p="*" 类似情况,所以链接中的热评第一代码可以ac,但手动输入这些case时系统给出的答案是正确的,链接所给的代码会报错,觉得也需要考虑这些corner case。
以上是关于leetcode 10-Regular Expression Matching(hard)的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode 10. Regular Expression Matching
leetcode 10. Regular Expression Matching
Leetcode 10: Regular Expression Matching
[LeetCode #10] Regular Expression Matching