zoukankan      html  css  js  c++  java
  • 10.Regular Expression Matching

    问题描述:

    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 letters a-z.
    • p could be empty and contains only lowercase letters a-z, and characters like . or *.

    Example 1:

    Input:
    s = "aa"
    p = "a"
    Output: false
    Explanation: "a" does not match the entire string "aa".
    

    Example 2:

    Input:
    s = "aa"
    p = "a*"
    Output: true
    Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
    

    Example 3:

    Input:
    s = "ab"
    p = ".*"
    Output: true
    Explanation: ".*" means "zero or more (*) of any character (.)".
    

    Example 4:

    Input:
    s = "aab"
    p = "c*a*b"
    Output: true
    Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".
    

    Example 5:

    Input:
    s = "mississippi"
    p = "mis*is*p*."
    Output: false

    思路:

    本题要求我们进行正则匹配。

    可匹配的符号有两个:

    1. ‘*’ 0个或多个前一个字符(字符和‘.’)

    2. ‘.’ 任意一个字母

    在这里需要注意的是:

    “.* ”可以匹配任意字符串因为其代表着0个或多个 '.' , 也就是说可以匹配空字符串以及任意字母组成的任意长度的字符串。

    参考:http://www.cnblogs.com/grandyang/p/4461713.html

    一开始我只想要要分情况,并且用指针来解决,但是由于‘*’可以代表零个或多个字符,所以对于怎样移动指针没有好的思路。

    大佬的讲解给了我思路。

    分情况:

    1.匹配字符串p为空,此时需判断待匹配字符串s是否为空

    2.匹配字符串p长度为1,需要判断s的长度以及s的内容,需要注意的是,若s长度为一,当p = ‘.’ 时也匹配成功

    3.匹配字符串p长度不为1:

      1). p[1] != '*': 前一段字符串长度不可变,可直接比较s[0] == p[0],若相等,对s和p下标为1到结尾的子串进行匹配。

      2).p[2] != '*': 前一段字符长度可能变化, 当s不为空的时候

                a. 若s[0] == p[0]时,可以尝试p.substr(2)与s进行匹配(因为前两个字符为"x*")

                b. 若p[0] == '.'时,可匹配任意字母,所以也直接尝试p.substr(2)与s进行匹配。

      当s为空或者上述两种情况都不成立时,直接比较 s 与 p.substr(2)          

    代码:

    class Solution {
    public:
        bool isMatch(string s, string p) {
            if(p.empty())
                return s.empty();
            if(p.size() == 1){
                return (s.size() == 1 && (p[0] == s[0] || p[0] == '.'));
            }
            if(p[1] != '*'){
                if(s.empty()) 
             return false; return (p[0] == s[0] || p[0] == '.' )&& isMatch(s.substr(1), p.substr(1)); } while(!s.empty() && (s[0] == p[0] || p[0] == '.')){ if(isMatch(s, p.substr(2))) return true; s = s.substr(1); } return isMatch(s, p.substr(2)); } };

    动态规划:

    居然可以用动态规划解啊朋友们!!

    m为s长度,n为p长度

    P[i][j] 代表 s的前i个字符能否跟p的前j个字符匹配。

    所以有前0个字符。

    P[0][0] = true;

    对第一列P[i][0]进行初始化,i 从1 到m-1为false

    对第一行P[0]进行初始化,从1开始,遇到‘*’时需要特殊讨论:

          if(p[i-1] == '*') dp[0][i] = dp[0][i-2]; 

    状态转移方程:

    1.  P[i][j] = P[i - 1][j - 1], if p[j - 1] != '*' && (s[i - 1] == p[j - 1] || p[j - 1] == '.');

    2.  P[i][j] = P[i][j - 2], if p[j - 1] == '*' and the pattern repeats for 0 times;
    3.  P[i][j] = P[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.'), if p[j - 1] == '*' and the pattern repeats for at least 1 times.

    时隔很久,回来填坑。

    代码:

    class Solution {
    public:
        bool isMatch(string s, string p) {
            int m = s.size();
            int n = p.size();
            vector<vector<bool>> dp(m+1, vector<bool>(n+1, false));
            dp[0][0] = true;
            for(int i = 1; i <= n; i++){
                if(p[i-1] == '*') dp[0][i] = dp[0][i-2]; 
            }
            for(int i = 1; i <= m; i++){
                for(int j = 1; j <= n; j++){
                    if(p[j-1] != '*'){
                        dp[i][j] = dp[i-1][j-1] && (s[i-1] == p[j-1] || p[j-1] == '.');
                    }else{
                        dp[i][j] = dp[i][j-2] || ((s[i-1] == p[j-2] || p[j-2] == '.') && dp[i-1][j]);
                    }
                }
            }
            return dp[m][n];
        }
    };
  • 相关阅读:
    log4net GetLogger(source).IsInfoEnabled = false
    nginx配置
    mysql数据库备份
    按序号批量更新某个字段
    MySql 执行 DELETE/UPDATE时,报 Error Code: 1175错误
    ef学习记录
    vue-cli3实行路径联想
    GitHub分支创建及合并
    Git本地分支和远程分支关联
    uniapp(三)
  • 原文地址:https://www.cnblogs.com/yaoyudadudu/p/9108851.html
Copyright © 2011-2022 走看看