Regular Expression Matching
来源:互联网 发布:域名云解析用吗 编辑:程序博客网 时间:2024/06/07 01:44
Regular Expression Matching - LeetCode
题目:
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
这道题要我们做一个正则表达式的匹配,正则表达式只包含字母、‘.’、‘*’。
函数声明bool isMatch(string s, string p)
其中s是待匹配字符串,p是正则表达式。
记录一下刚开始走过的坑:
最初有个很单纯的想法,从头到尾遍历一遍s,对于每个s中的字符,去检查一下p中下一个字符是否与之匹配,如果p的下一个字符是‘*’那么就要做一些特殊判断,总之分了挺多情况。
但是很遗憾这个方法行不通,,我碰到了下面这个例子:
s = “aaa”
p = “ab*a*c*a”
如果按照我刚才的方法,这里无法确定p中的a*到底对应s中几个a,也就是说当p的下一个字符为‘*’时,我不能确定该把这个‘*’当成‘a’来处理,还是结束这个‘*’去检查下一个字符。在这个例子中,如果把‘a*’中的‘*’当成‘a’来处理那就错了。
就算反过来,从尾部开始匹配也还是有这个问题。
正确的方法:
搜了一下正则表达式匹配算法,看到一篇博客,使用动态规划做的。不过这篇博客里的题目和我做的这道题还是有差别的,所以需要修改很多地方。
又搜了一下动态规划,简单的学了一下(大一就听说过这个高端的算法,,然而一直没有去学),再参考第一篇博客里的代码得出了这道题的答案。
其实主要的问题就是这个‘*’,不能确定它到底对应几个字符,这样就只能(应该是只能吧。。)用遍历的方法,遍历每一种可能,但如何遍历这个是难点。
这里用了一个二维bool数组m[128][128],m[i][j]记录s的长度为i的前缀与p的长度为j的前缀是否匹配,如果匹配m[i][j]就为true。
这样就可以开始遍历了,首先m[0][0]是显然为true的,
然后对i=1,j=1,2,…,p.length,分别求出m[i][j]
再对i=2,j=1,2,…,p.length,分别求出m[i][j]
直到i=s.length,j=1,2,…,p.length。
递推式为:
if (p[j] == '*') { // 检查到一个'*'后,'*'前面的那个字符是可以忽略的,所以要修改一下某些匹配关系 if (!m[i][j+1]) m[i][j+1] = m[i][j-1]; m[i+1][j+1] = m[i+1][j-1] || m[i+1][j] || (m[i][j+1] && (p[j-1] == s[i] || p[j-1] == '.'));} else { m[i+1][j+1] = m[i][j]&&(p[j] == s[i] || p[j] == '.');}
完整代码:
#include <iostream>#include <cstdlib>using namespace std;class Solution {public: bool isMatch(string s, string p) { if (p.length() == 0 && s.length() != 0) return false; if (p == ".*") return true; bool m[128][128] = {0}; m[0][0] = true; int i = 0, j = 0; int sum = 0; for (j = 0; j < p.length(); j++) { if (p[j] != '*') sum++; else sum--; if (sum == 0) m[0][j+1] = true; } for (i = 0; i < s.length(); i++) { for (j = 0; j < p.length(); j++) { if (p[j] == '*') { if (!m[i][j+1]) m[i][j+1] = m[i][j-1]; m[i+1][j+1] = m[i+1][j-1] || m[i+1][j] || (m[i][j+1] && (p[j-1] == s[i] || p[j-1] == '.')); } else { m[i+1][j+1] = m[i][j]&&(p[j] == s[i] || p[j] == '.'); } } } return m[s.length()][p.length()]; }};
做这道题跨时7个小时,虽然7个小时里不是一直在做这题。看了下最快的方法也是用动态规划做的,思路应该大同小异所以就没有细看。。
- LeetCode: Regular Expression Matching
- LeetCode: Regular Expression Matching
- leetcode Regular Expression Matching
- [Leetcode] Regular Expression Matching
- Regular Expression Matching
- Regular Expression Matching
- [LeetCode]Regular Expression Matching
- Regular Expression Matching
- LeetCode-Regular Expression Matching
- Regular Expression Matching
- Regular Expression Matching LeetCode
- Regular Expression Matching
- LeetCode | Regular Expression Matching
- LeetCode: Regular Expression Matching
- Leetcode: Regular Expression Matching
- [LeetCode] Regular Expression matching
- [LeetCode] Regular Expression Matching
- LeetCode Regular Expression Matching
- AQS共享锁的实现原理
- arch Linux无法启动Shadowsocks qt5
- [java多线程]如何安全的退出线程
- c/c++可执行程序的生成过程
- java定时任务,每天定时执行任务
- Regular Expression Matching
- [笔记]char* 转 unsigned char*
- 对象内存布局(MSVC2017)
- haxe 第一期 入门骗 (谷歌翻译+转载)
- Oracle给账户解锁
- Codeforces 235C Cyclical Quest 后缀自动机
- Python安装
- Xcode中描述文件的真实目录
- 【Java编程思想笔记】第一章——对象导论