leetcode 10 Regular Expression Matching(Dynamic Programming)
来源:互联网 发布:百度网络硬盘登陆 编辑:程序博客网 时间:2024/06/07 13:21
题意:
'.' 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") → falseisMatch("aa","aa") → trueisMatch("aaa","aa") → falseisMatch("aa", "a*") → trueisMatch("aa", ".*") → trueisMatch("ab", ".*") → trueisMatch("aab", "c*a*b") → true
设左边字符串为s,右边字符串为p。判断是否可以用右边的字符串完全匹配左边的字符串。
其中‘.’可以代表任何一个单个字符,‘*’代表其之前的字符有任意个(例如"c*"可以代表 没有c,1个c,2个c...)
倒数第二个样例解释: “.*”用来代表“..”,“..”可以完全匹配“ab”
倒数第一个样例解释:“c*a*b”中“c*”代表空字符(0个c),“a*”代表“aa”
解决方法:
1.暴力深搜
刚开始我们需要解决的问题是:
判断s和p从各自的起始位置s[0] p[0]开始,直到他们的结束位置s[s.length()-1],p[p.length()-1]为止是否能完全匹配。
假设现在已经匹配到了s[i],p[j](二者之前的子串完全匹配),现在问题转化成:
判断s和p从各自的起始位置s[i] p[j]开始,直到他们的结束位置s[s.length()-1],p[p.length()-1]为止是否能完全匹配。
以上是状态转化。
由于p中字符"*" "."的存在,要考虑到的问题多了一些:
(1)当前状态起始位置为s[i] p[j],p[j+1] != '*':若s[i] == p[j], 状态转移到起始位置为s[i+1] p[j+1];若s[i] != p[j],返回false。
(2)当前状态起始位置为s[i] p[j],p[j+1] == '*':
因为*的特殊功能,所以p[j]这个字符,可以当作空字符(不存在),这样状态就转换为:状态起始位置为s[i] p[j+2]
可以当作1个字符:若s[i] == p[j], 状态转移到起始位置为s[i+1] p[j+2];
可以当作2个字符:若s[i] == p[j]且s[i+1] == p[j], 状态转移到起始位置为s[i+2] p[j+2];
可以当作3个字符:若s[i] == p[j]且s[i+1] == p[j]且s[i+2] == p[j], 状态转移到起始位置为s[i+3] p[j+2];
。。。。。。
代码:
class Solution {public: bool dfs(string s, string p, int i, int j){ if(j==p.length()) return i==s.length(); //p[j+1] != '*'; if(j==p.length()-1 || p[j+1]!='*') { if(i==s.length()|| s[i]!=p[j] && p[j]!='.') return false; else return dfs(s,p,i+1,j+1); } //p[j+1]=='*' while(i<s.length() && (p[j]=='.' || s[i]==p[j])) { if(dfs(s,p,i,j+2)) return true; i++; } return dfs(s,p,i,j+2); }public: bool isMatch(string s, string p) { return dfs(s, p, 0, 0); }};
class Solution { bool vis[1005][1005]; bool res[1005][1005];public: bool dfs(string s, string p, int i, int j){ if(vis[i][j]) return res[i][j]; vis[i][j] = true; if(j==p.length()) return res[i][j] = (i==s.length()); if(j==p.length()-1 || p[j+1]!='*') { if(i==s.length()|| s[i]!=p[j] && p[j]!='.'){ return res[i][j] = false; } else{ return res[i][j] = dfs(s,p,i+1,j+1); } } //p.charAt(j+1)=='*' while(i<s.length() && (p[j]=='.' || s[i]==p[j])) { if(dfs(s,p,i,j+2)){ return res[i][j] = true; } i++; } return res[i][j] = dfs(s,p,i,j+2); }public: bool isMatch(string s, string p) { //memset(vis, false, sizeof(vis)); return dfs(s, p, 0, 0); }};
2.动态规划
/** * f[i][j]: if s[0..i-1] matches p[0..j-1] * if p[j - 1] != '*' * f[i][j] = f[i - 1][j - 1] && s[i - 1] == p[j - 1] * if p[j - 1] == '*', denote p[j - 2] with x * f[i][j] is true iff any of the following is true * 1) "x*" repeats 0 time and matches empty: f[i][j - 2] * 2) "x*" repeats >= 1 times and matches "x*x": s[i - 1] == x && f[i - 1][j] * '.' matches any single character */
这是我看到的一个思路,感觉特别好。
f[i][j]状态定义为s的前i 个字符 与 p的前j个字符是否完全匹配:true/false
(1)p[j-1] != '*'时,直接根据f[i-1][j-1]和s[i-1] p[j-1]转移状态
if p[j - 1] != '*' f[i][j] = f[i - 1][j - 1] && s[i - 1] == p[j - 1]
(2)p[j-1] == '*'时,
p[j-2]可以当作空字符,此时f[i][j]状态由f[i][j-2]状态直接得到;
p[j-1]可以当作>=1个字符:此时若s[i-1] == p[j-2]只需要f[i-1][j]为true,s[i-1]这个字符就可以用‘*’重复出来的p[j-2]来匹配(而不用管之前这个p[j-1]已经重复造出来过几个p[j-2])
代码:为了加深自己的理解,自己用java写了一下。
public class Solution { public static boolean isMatch(String s, String p) { boolean[][] f = new boolean[s.length()+1][p.length()+1]; f[0][0] = true; boolean tmp = true; for(int j = 1; j <= p.length(); j++){ if(tmp && p.charAt(j-1) != '*' && j < p.length() && p.charAt(j) != '*') tmp = false; if(tmp && j == p.length() && p.charAt(j-1) != '*') tmp = false; f[0][j] = tmp; } for(int i = 1; i <= s.length(); i++){ for(int j = 1; j <= p.length(); j++){ if(p.charAt(j-1) != '*'){ f[i][j] = f[i-1][j-1] && (s.charAt(i-1) == p.charAt(j-1) || p.charAt(j-1) == '.'); } else{ f[i][j] = f[i][j-2] || ((s.charAt(i-1) == p.charAt(j-2) || p.charAt(j-2) == '.') && f[i-1][j]); } } } //System.out.println(f[1][2]); return f[s.length()][p.length()]; }}
希望对大家有所帮助,欢迎大家将任何问题在回复区讨论。
- leetcode 10 Regular Expression Matching(Dynamic Programming)
- Leetcode【10】:Regular Expression Matching
- [leetcode 10] Regular Expression Matching
- LeetCode(10) Regular Expression Matching
- [leetcode 10] Regular Expression Matching
- leetcode.10------------Regular Expression Matching
- [leetcode] 10 Regular Expression Matching
- [leetcode] 10 Regular Expression Matching
- LeetCode 10:《Regular Expression Matching》
- leetcode 10: Regular Expression Matching
- LeetCode 10 - Regular Expression Matching
- Leetcode #10 Regular Expression Matching
- leetcode 10 -- Regular Expression Matching
- LeetCode 10: Regular Expression Matching
- leetcode 10 -- Regular Expression Matching
- leetcode-10Regular Expression Matching
- leetcode-10 Regular Expression Matching
- leetcode 10: Regular Expression Matching
- split方法拆分字符串
- 安卓引导页划动中页面消失、异常退出问题
- 欢迎使用CSDN-markdown编辑器
- jQuery中的DOM操作
- 第四章 面向对象(下)
- leetcode 10 Regular Expression Matching(Dynamic Programming)
- Spring源码学习--自定义标签
- 第六讲:index$watch.html
- Html--部分标签的使用
- 【51Nod】1008 N的阶乘 mod P
- linux下TCP/IP及内核参数优化调优(TIME_WAIT)
- opencv结合MFC打开图片
- Delphi THTTPRIO 控件调用webservice超时问题
- hdu 2528 Mayor's posters(线段树+离散化)