支持 ‘.‘ 和 ‘*‘ 的正则表达式匹配


/*
https://leetcode.cn/problems/regular-expression-matching/?favorite=2cktkvj
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

 
示例 1:

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。
示例 2:

输入:s = "aa", p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:

输入:s = "ab", p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
 

提示:

1 <= s.length <= 20
1 <= p.length <= 30
s 只包含从 a-z 的小写字母。
p 只包含从 a-z 的小写字母,以及字符 . 和 *。
保证每次出现字符 * 时,前面都匹配到有效的字符

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/regular-expression-matching
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

*/

// 思路:开始用了s,p往前递进,逐步判断的方式,总有测试case无法正确处理,看了CSDN上用动态规划的方法,重新实现了

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>

#define MAX_P_LEN 32
#define MAX_IN_LEN 24

enum MATCH_MODE {
    ANY_ONE = 1, // .
    ANY_MORE = 2,  // .*
    FIXED_ONE = 4,  // a
    FIXED_MORE = 8, // a*
};

struct regular_exp {
    char expr;
    enum MATCH_MODE mode;
};

//static bool matched_arr[MAX_P_LEN][MAX_IN_LEN] = {false};
//static struct regular_exp expr_arr[MAX_P_LEN];

#define MATCH_ONE '.'
#define MATCH_PRE '*'

static int parse_regular_exp(const char *expr, struct regular_exp *expr_arr)
{
    const char *p = expr;
    int size = 1;

    while ((*p != '\0') && (size < MAX_P_LEN)) {
        expr_arr[size].expr = *p;

        if (*(p + 1) == MATCH_PRE) {
            if (*p == MATCH_ONE) {
                expr_arr[size].mode = ANY_MORE;
            } else {
                expr_arr[size].mode = FIXED_MORE;
            }

            p++;
        } else if (*p == MATCH_ONE) {
            expr_arr[size].mode = ANY_ONE;
        } else {
            expr_arr[size].mode = FIXED_ONE;
        }

        size++;
        p++;
    }

    return size;
}

static bool do_match(int row, int col, char in_char,  struct regular_exp *expr_arr, bool matched_arr[][MAX_IN_LEN])
{
    bool ret = false;

    switch (expr_arr[row].mode) {
    case ANY_ONE:
    case FIXED_ONE:
        if ((expr_arr[row].mode == FIXED_ONE) && (in_char != expr_arr[row].expr)) {
            break;
        }

        //handle char match case
        ret = matched_arr[row - 1][col - 1];
        
        break;
    case ANY_MORE:
    case FIXED_MORE:
        if ((in_char == expr_arr[row].expr) || (expr_arr[row].mode == ANY_MORE)) { //match the char
            ret = matched_arr[row - 1][col - 1] || matched_arr[row][col - 1] || matched_arr[row - 1][col];
        } else { //not match the char, could ignore
            ret = matched_arr[row - 1][col];            
        }

        break;
    default:
        break;
    }

    return ret;
}

bool isMatch(const char *s, const char *p)
{
    //just for leetcode, not need malloc for small memory
    bool matched_arr[MAX_P_LEN][MAX_IN_LEN] = {false};
    struct regular_exp expr_arr[MAX_P_LEN];

    int in_size = strlen(s) + 1;  // 0 as assisted data
    int expr_size = parse_regular_exp(p, expr_arr); // index 0 as assisted data
    int i = 0, j = 0;

    assert(in_size < MAX_IN_LEN);
    assert(strlen(p) < MAX_P_LEN);
    memset(matched_arr, sizeof(matched_arr), 0);

    //row 0 and col0 as assist data, set its char as 0 and regular exp as 0:
    matched_arr[0][0] = true;
    for (i = 1; i < expr_size; i++) {
        if (expr_arr[i].mode & (ANY_MORE | FIXED_MORE)) {
            matched_arr[i][0] = matched_arr[i - 1][0];
        }
    }

    for (i = 1; i < expr_size; i++) {
        for (j = 1; j < in_size; j++) {
            matched_arr[i][j] = do_match(i, j, s[j - 1], expr_arr, matched_arr);
        }
    }

    return matched_arr[i-1][j-1];
}

#define IN_SIZE  256
static char in_str[IN_SIZE];
static char reg_exp[IN_SIZE];

int main(int argc, char *argv[])
{
    printf("please input two strings: in-string & reg-expr\n");
    
    scanf("%s %s", in_str, reg_exp);
    printf("check match in: %s, exp: %s\n", in_str, reg_exp);

    printf("matched: %s\n", isMatch(in_str, reg_exp) ? "true" : "false");

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值