LeetCode 10. Regular Expression Matching(正则表达式匹配)

题目描述:

    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

分析:
    题意:给定两个字符串,一般的字符都是一一对应匹配,存在两个特殊字符:①'.' 可以匹配任意一个字符; '*'可以匹配零个或者多个它自身的前驱字符。判断两个字符串是否能完成匹配。
    思路:由于两个特殊字符的存在,那么匹配就出现了多种可能性,如果两个字符串足够长,使用DFS暴力搜索绝对会超时。我们采用动态规划的思想来求出递推公式:假设字符串s和p的长度分别为n1、n2,构造数组dp[n1+1][n2+1],初始化为false(其中dp[0][0] = true)。假设我们当前考察s[0→(i-1)]和p[0→(j-1)]的匹配关系,那么根据p[j-1]的取值分两类讨论。
    ①p[j-1]不为'*'时,如果s[0→(i-2)]和p[0→(j-2)]匹配,我们只需要s[i-1]和p[j-1]相等或者p[j-1]为'.'即可。
        dp[i][j] = (i - 1 >= 0) && dp[i - 1][j - 1] && ((s[i - 1] == p[j - 1]) || (p[j - 1] == '.'))
    ②p[j-1]为'*'时,又分别为两种情况:
    Ⅰ.p[j-1]此时恰好停止匹配前驱字符(即匹配零个),此时我们只需要保证s[0→(i-1)]和p[0→(j-3)]匹配;Ⅱ.p[j-1]还在继续匹配前驱字符,我们必须保证s[0→(i-2)]和p[0→(j-1)]匹配,与此同时,p[j-2]需要和s[i-1]相等或者p[j-2]为'.'即可。
        dp[i][j] = (j - 2 >= 0 && dp[i][j - 2]) || (i - 1 >= 0 && j - 2 >= 0 && dp[i - 1][j] && ((s[i - 1] == p[j - 2]) || (p[j - 2] == '.')))

代码:

#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    bool isMatch(string s, string p) {
		int n1 = s.length(), n2 = p.length();
		// Exceptional Case: 
		if(n1 == 0 && n2 == 0){
			return true;
		}
		if(n1 != 0 && n2 == 0){
			return false;
		}
		// create
		vector<vector<bool>> dp(n1 + 1, vector<bool>(n2 + 1, false));
		// init
		dp[0][0] = true;
		for(int i = 1; i <= n1; i++){
			dp[i][0] = false;
		}
		// dp
		for(int i = 0; i <= n1; i++){
			for(int j = 1; j <= n2; j++){
				if(p[j - 1] != '*'){
					dp[i][j] = (i - 1 >= 0) && dp[i - 1][j - 1] && ((s[i - 1] == p[j - 1]) || (p[j - 1] == '.'));
				}
				else if(p[j - 1] == '*'){
					// attention: ((s[i - 1] == p[j - 2]) || (p[j - 2] == '.')) is different from (s[i - 1] == p[j - 2] || p[j - 2] == '.')
					dp[i][j] = (j - 2 >= 0 && dp[i][j - 2]) || (i - 1 >= 0 && j - 2 >= 0 && dp[i - 1][j] && ((s[i - 1] == p[j - 2]) || (p[j - 2] == '.')));
				}
			}
		}
        return dp[n1][n2];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值