美文网首页
正则表达式

正则表达式

作者: 王王王王王景 | 来源:发表于2019-07-22 20:50 被阅读0次

正则表达式匹配

题目描述:

给定一个字符串 (s) 和一个字符模式 (p)。实现支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符。
'*' 匹配零个或多个前面的元素。

解题思路:

(1)这个题目是典型的二维动态规划题目;
eg:
s = "aaab"
p = "cab"
1.1 首先建立dp数组dp[s.size() + 1][p.size() + 1]
需要从空字符串进行思考,所以需要+1
其中dp[i][j]对应的字符比较应该是s[i-1]和p[j-1]

dp '' c * a * b
'' true false true false true false
a false false false true true false
a false false false false true false
a false false false false true false
b false false false false false true

(2)问题主要集中在如何处理号,号的作用是两个
2.1 去除前面一个无关的字符,dp[i][j]的结果就变成了dp[i][j-2]; 比较 s[0:i]和p[0:j-3]的匹配结果
2.2 重复前面一个字符n次(n可以为0)dp[i][j]的结果需要看 s[i-1]和p[j-2]的匹配结果 和 dp[i-1][j]的结果

代码:

class Solution {
public:
    bool isMatch(string s, string p) {
    int s_len = s.size(), p_len = p.size();
    // dp[i][j]是由s[i-1]和p[j-1]决定的
    // 其中i=0 和 j=0都是表示空字符串的时候
    bool **dp = new bool*[s_len + 1];
    for(int i = 0; i <= s_len; ++i){
        dp[i] = new bool[p_len + 1];
    }
    // p为空,但s不为空时候肯定是false
    for(int i = 0; i <= s_len; ++i)
        dp[i][0] = false;
    
    // 两者都为空的时候为true
    dp[0][0] = true;
    
    for(int i = 0; i <= s_len; ++i)
        for(int j = 1; j <= p_len; ++j){ // j=0的情况已经初始化了
            if(p[j-1] == '*'){
                /*
                 p[j-1]=='*'的时候有两种情况:
                 (1)当*号的作用是去除p[j-2],因此需要看s[0:i-1]和p[0:j-3]的匹配效果==>dp[i][j-2];
                    同时还考虑到了i=0的情况,*对于dp[0][j]的填充;同时就算p[j-1] == s[i -1],同样也可能需要去除p[j-2],eg: a 与 aa*
                 (2)p[j-1] == s[i -1]或者p[j-1] == '.'的时候,*号的作用是重复p[j-1]这个字符n(n可以为0)次,s[0:i-1]和p[0:j-1]如果能匹配的上,
                 证明s[0:i-2]和p[0:j-1]肯定也是匹配上的==>dp[i-1][j]; eg: aab 与 ab*匹配不上
                 */
                dp[i][j] = (dp[i][j-2]) || (i > 0 && (p[j-2] == s[i -1] || p[j-2] == '.') && dp[i-1][j]);
            }else{
                // 正常比较情况
                dp[i][j] =  i > 0 && dp[i-1][j-1] && (p[j-1] == '.' || p[j-1] == s[i-1]);
            }
        }
    
    return dp[s_len][p_len];
    }
};
 
// 递归的方式
/*
bool isMatch(string s, string p) {
        if(0 == p.size()) return (0 == s.size());
        bool is_match = s.size() > 0 && (s[0] == p[0] || p[0] == '.');
        if(p.size() > 0 && p[1] == '*'){
            return isMatch(s, p.substr(2)) || (is_match && isMatch(s.substr(1), p));
        }else{
            return is_match && isMatch(s.substr(1), p.substr(1));
        }
 }
*/

自己编写的版本:

class Solution {
public:
    bool isMatch(string s, string p) {
        bool **dp;
        int len_s = s.size(), len_p = p.size();
        dp = new bool*[len_s + 1];
        for(int i = 0; i < len_s + 1; ++i) {
            dp[i] = new bool[len_p + 1];
        }
        dp[0][0] = true;
        for(int i = 1; i < len_s + 1; ++i) {
            dp[i][0] = false;
        }
        for(int i = 0; i < len_s + 1; ++i) {
            for(int j = 1; j < len_p + 1; ++j) {
                // *比较特殊需要单独判断 
                if(p[j - 1] == '*') {
                    // 当前dp[i][j]的前一个位置 s[i - 1] 和 p[j - 1]是可以匹配的
                    // 如果前面字符串就是可以匹配的了,那么*号的作用就是重复0次
                    // 如果前面的字符串不能完成匹配
                    if(i > 0 && j > 1 && (p[j - 2] == s[i - 1] || p[j -2] == '.')) {
                        // 重复前面的n次  --> dp[i-1][j]  ; 去除多余的相同字符 --->dp[i][j-2]
                        dp[i][j] = dp[i - 1][j] || dp[i][j -2];
                    } else if(j > 1){  // 前面字符不相等的时候用*进行删除来获取是否能够匹配
                        dp[i][j] = dp[i][j -2];
                    } else { // *放在最开始的时候是不允许的(前面必须有字符),不能匹配
                        dp[i][j] = false;
                    }
                } else {
                    if(i > 0 && (s[i-1] == p[j-1] || p[j-1] == '.'))
                        dp[i][j] = dp[i - 1][j - 1];
                    else
                        dp[i][j] = false;
                }
            }
        }
        // for(int i = 0; i < len_s + 1; ++i) {
        //     for(int j = 0; j < len_p + 1; ++j) {
        //         if(dp[i][j] == true)
        //             cout<<"1"<<"  ";
        //         else
        //             cout<<"0"<<"  ";
        //     }
        //     cout<<endl;
        // }
        return dp[len_s][len_p];
    }
};

相关文章

  • Linux命令行与Shell脚本编程大全-shell正则表达式

    本章内容: 定义正则表达式 了解基本正则表达式 扩展正则表达式 创建正则表达式 定义正则表达式 正则表达式是你定义...

  • 正则相关

    正则表达式基本语法 正则表达式常见字符 正则表达式特殊字符 正则表达式数量词 正则表达式边界匹配 正则表达式逻辑或...

  • 正则表达式系列-1

    正则表达式系列-1正则表达式系列-2正则表达式系列-3正则表达式系列-4 什么是正则表达式 正则表达式就是用事先定...

  • 正则表达式

    正则表达式 - 教程正则表达式 - 简介正则表达式 - 语法正则表达式 - 元字符正则表达式 - 运算符优先级正则...

  • Python基础入门 - 正则表达式与综合实战

    1. 初识正则表达式 1.1 介绍 步骤介绍正则表达式入门及应用正则表达式的进阶正则表达式案例 1.2 正则表达式...

  • Java正则表达式参考

    Java正则表达式入门 java正则表达式应用 深入浅出之正则表达式(一) 深入浅出之正则表达式(二) 正则表达式...

  • 正则表达式

    正则表达式 正则表达式就是记录文本规则的代码 正则表达式常用的元字符 正则表达式常用的限定符 正则表达式举例:这里...

  • Python爬虫(十)_正则表达式

    本篇将介绍python正则表达式,更多内容请参考:【python正则表达式】 什么是正则表达式 正则表达式,又称规...

  • python正则表达式

    本篇将介绍python正则表达式,更多内容请参考:【python正则表达式】 什么是正则表达式 正则表达式,又称规...

  • 正则表达式

    了解正则表达式基本语法 能够使用JavaScript的正则对象 正则表达式简介 什么是正则表达式 正则表达式:用于...

网友评论

      本文标题:正则表达式

      本文链接:https://www.haomeiwen.com/subject/fleglctx.html