LeetCode Regular Expression Matching(.和*通配符匹配)

本文介绍了一种正则表达式匹配算法,包括递归和动态规划两种实现方式。递归方法通过判断字符是否匹配来逐步推进匹配过程,而动态规划则通过构建二维数组来记录中间结果,从而提高效率。

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

给出text和pattern,pattern中可以使用通配符.和*,.表示匹配任意字符,*表示匹配上一个字符

从text和pattern的第一个字符开始做匹配

1.第一个字符匹配成功,要么第一个字符相等或者pattern的首字符为.

2.*字符只可能为pattern的开始匹配位置计数开始的第2个,如果第2个为*,

(1)直接路过pattern的前两个

(2)如果首字符匹配成功,则从text的下一个字符开始与pattern作匹配

3.如果首字符匹配成功,从text和pattern的下一个字符开始作匹配

递归代码如下:

class Solution(object):
    def isMatch(self, s, p):

        if not p:
            return not s


        firstmatch = bool(s) and p[0] in {s[0], '.'}

        if len(p) >= 2 and p[1] == '*':
            return (self.isMatch(s, p[2:]) or
                    firstmatch and self.isMatch(s[1:], p))
        else:
            return firstmatch and self.isMatch(s[1:], p[1:])

动态规划算法

用f(i,j)表示text[i:]和pattern[j:]是否匹配,则

f(i,j) = 模式串的开始的第2个字符为*时,f(i, j + 2),如果首字符匹配为f(i + 1, j)

具体代码如下:

enum Result
{
	TRUE, FALSE
}

public class Solution 
{
	private Result[][] result;
	
	public boolean isMatch(String s, String p)
	{
		result = new Result[s.length() + 1][p.length() + 1];
		
		return dp(0, 0, s, p);
	}
	
	private boolean dp(int i, int j, String s, String p)
	{
		if (result[i][j] != null)
		{
			return result[i][j] == Result.TRUE;
		}
		
		boolean ans;
		
		if (j == p.length())
		{
			ans = i == s.length();
		}
		else 
		{
			boolean firstMatch = (i < s.length() && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '.'));
			
			if (j + 1 < p.length() && p.charAt(j + 1) == '*')
			{
				ans = dp(i, j + 2, s, p) || (firstMatch && dp(i + 1, j, s, p));
			}
			else 
			{
				ans = firstMatch && dp(i + 1, j + 1, s, p);
			}
		}
		
		result[i][j] = ans ? Result.TRUE : Result.FALSE;
		
		return ans;
		
	}
	
}

动态规划的递推实现 

func isMatch(s string, p string) bool {
	var sLen int = len(s)
	var pLen int = len(p)

	var dp [][]bool
	for i := 0; i < sLen + 1; i++ {
		s1 := make([]bool, pLen + 1)
		for j := 0; j < pLen + 1; j++ {
			s1 = append(s1, false)
		}
		dp = append(dp, s1)
	}
	dp[sLen][pLen] = true

	for i := sLen; i >= 0; i-- {
		for j := pLen - 1; j >= 0; j-- {
			var firstMatch bool = i < sLen && s[i] == p[j] || p[j] == '.'

			if j + 1 < pLen && p[j + 1] == '*' {
				dp[i][j] = dp[i][j + 2] || (firstMatch && dp[i + 1][j])
			} else {
				dp[i][j] = firstMatch && dp[i + 1][j + 1]
			}
		}
	}

	return dp[0][0]
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值