LeetCode 10 Regular Expression Matching

本文介绍了一种使用动态规划解决正则表达式匹配问题的方法,重点解析了如何处理特殊字符'.'和'*',并提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

说明:*号之前的字符可以出现多次,比如说a*b可以和ab也可以和aab匹配,甚至也可以和b匹配,因为a可以出现0次。
思路:设定i,j作为两个游标,分别指向s[i],p[j],dp[i][j]代表s[i]和p[j]是否匹配  以及 i,j之后的字符是否已经匹配。

这里重点讲解 j + 1 < pn && p[j + 1] == '*' 的情况。因为p[j + 1] == '*' ,而'*' 可以代表0个或者多个p[j] 。

如果'*' 代表0个p[j],那么,我们就无视p[j],同时由于p[j+1]=='*',因此p[j+1]也要一起被我们无视了,因此p的游标 j 忽略p[j+1],p[j]两位,依然指向p[j+2],s的游标 i 不动,依然指向 s[i],于是我们比较 p[j+2]和s[i]是否相等即可,即dp[i][j+2]。例:我们看s= cb和 p = ca*b是否匹配,因为*可以当作0个a,所以是匹配的,这个时候当游标 j 指向p[1]='a'的时候,由于p[2]='*'因此我们就直接判断p[3]是否等于s[1]即可。

如果'*' 代表1个或者多个p[j],那么,如果s[i] == p[j],dp[i][j]的值就依赖于dp[i+1][j],因为p[j+1]=='*',因此p[j]可以循环利用。例如s =  caaaab、p = ca*b,游标 j 指向p[1]='a'的时候,由于p[2]='*',此时如果游标 i 指向s[4]='a'=p[1],只要dp[5][1] ==dp[5][3] =true,因此dp[4][1]也为ture;如果 i 指向s[3]=='a'=p[1],只要dp[4][1]为ture……

Runtime: 32 ms beats 61.31% of java submissions. dp解法效率上比起动辄上百毫秒的递归好很多了。

	public boolean isMatch(String ss, String pp) {
		int pn = pp.length(), sn = ss.length();
		boolean[][] dp = new boolean[sn + 1][pn + 1];
		char[] s = ss.toCharArray(), p = pp.toCharArray();
		dp[sn][pn] = true;
		for (int i = sn; i >= 0; i--)
			for (int j = pn - 1; j >= 0; j--)
				if (j + 1 < pn && p[j + 1] == '*')
					dp[i][j] = dp[i][j + 2] || 
							i < sn && (p[j] == '.' || s[i] == p[j]) && dp[i + 1][j];
				else dp[i][j] = i < sn && (p[j] == '.' || s[i] == p[j]) && dp[i + 1][j + 1];
		return dp[0][0];
	}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值