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个小时里不是一直在做这题。看了下最快的方法也是用动态规划做的,思路应该大同小异所以就没有细看。。

原创粉丝点击