常用算法之正则表达式匹配

正则表达式匹配

介绍

请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。

示例 1:

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

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

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

输入:
s = “aab”
p = “cab”
输出: true
解释: 因为 ‘*’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。
示例 5:

输入:
s = “mississippi”
p = “misisp*.”
输出: false
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母以及字符 . 和 ,无连续的 '’。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof

代码
思路:碰到‘*’只有两种选择,选择一:不进行匹配,选择二:匹配一个字符。
#include <bits/stdc++.h>
using namespace std;

unordered_map<int,unordered_map<int,bool>> memo;
string s,p;

bool isMatch(int i,int j){
	// p.size() == 0时,特判
	if (j >= (int)p.size()) return i >= (int)s.size();
	// s.size() == 0时,特判。
    if (i == (int)s.size()){
        stack<char> stk;
        for (int k = j;k < (int)p.size();++k){
            if (p[k] == '*'){
                if (stk.empty()) return false;
                else stk.pop();
            }
            else {
                stk.push(p[k]);
            }
        }
        return stk.empty();
    }
    if (memo.count(i) && memo[i].count(j)) return memo[i][j];
    bool first = (i < (int)s.size() && p[j] == s[i]) || (p[j] == '.');
    if (j + 1 < (int)p.size() && p[j + 1] == '*'){
        memo[i][j] = isMatch(i,j + 2) || (first && isMatch(i + 1,j));
        return memo[i][j];
    }
    memo[i][j] = first && isMatch(i + 1,j + 1);
    return memo[i][j];
}

int main(void){
	s = "ab";
    p = ".*c";

    bool ans = isMatch(0,0);

    if (ans) cout << "true" << endl;
    else cout << "false" << endl;;
	return 0;
}
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class RegularExpression {
    public static Map<Integer,Map<Integer,Boolean>> memo = new HashMap<>();
    public static String text,pattern;

    public static void main(String[] args) {
//        String text = "mississippi";
//        String pattern = "mis*is*p*.";
        text = "ab";
        pattern = ".*c";
        boolean ans = isMatch(0,0);
        if (ans) System.out.println("true");
        else System.out.println("false");
    }

    public static boolean isMatch(int i,int j){
        if (j >= pattern.length()) return i >= text.length();
        if (i == text.length()){
            Stack<Character> stk = new Stack<>();
            for (int k = j;k < pattern.length();++k){
                if (pattern.charAt(k) == '*'){
                    if (stk.isEmpty()) return false;
                    else stk.pop();
                }
                else {
                    stk.push(pattern.charAt(k));
                }
            }
            return stk.isEmpty();
        }
        if (memo.containsKey(i) && memo.get(i).containsKey(j)) return memo.get(i).get(j);
        boolean first = (pattern.charAt(j) == text.charAt(i)) || (pattern.charAt(j) == '.');
        if (j + 1 < pattern.length() && pattern.charAt(j + 1) == '*'){
            boolean flag = isMatch(i,j + 2) || (first && isMatch(i + 1,j));
            Map<Integer,Boolean> temp = new HashMap<>();
            temp.put(j,flag);
            memo.put(i,temp);
            return flag;
        }

        boolean flag =  first && isMatch(i + 1,j + 1);
        Map<Integer,Boolean> temp = new HashMap<>();
        temp.put(j,flag);
        memo.put(i,temp);
        return flag;

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值