【leetcode高频问题-DP】10.(Hard) Regular Expression Matching

解题思路

这是一道非常巧妙的DP题
s表示string,是一串字符串,p表示pattern,是正则表达式模式。
解题的方法是建立一个二维dp数组,分成 (0,0)单个空第一行第一列其他这4个部分去搞。

假设p的长度是m,s的长度是n,首先创建一个二维数组,长这个样子:
在这里插入图片描述
位置1:空字符串"“和空模式”“匹配,直接是true
位置2:字符串"mis"和空模式”“匹配,毫无疑问是false
位置3:空字符串”“和模式"mis"匹配,毫无疑问是false
位置4:字符串"missis"和模式"mis*i"匹配
位置5:字符串"mississippi"和模式"mis*is*p*”,是我们最终需要的答案

对于这个表格来说,第一行和第一列是比较直观好填的(注意这里第一行和第一列都不包括(0,0)这个点):
在这里插入图片描述
第一行相当于一个空的模式去匹配一个非空的字符串,结果必然是false:
在这里插入图片描述


第一列相当于空的字符串去匹配非空的模式,只有当模式是"x*x*x*…"这种形式时才能匹配上空字符串。例如模式为"a*b*“或者”.*a*"等。
代码为:

for(int i=1;i<=m;i++) {
    		if(i%2==0) 	dp[i][0]=((p.charAt(i)=='*')&&dp[i-2][0]);
    		else	dp[i][0]=false;
}

上面的例子处理下来是这样:
在这里插入图片描述


中间的部分从上到下从左到右依次处理,位置(i,j)上的值表示模式p的前i个和字符串s的前j个字符进行匹配。这里分情况讨论:
1.p.charAt(i) == s.charAt(j) || p.charAt(i) == '.':则dp[i][j]=dp[i-1][j-1]
2.p.charAt(i) == '*':

  • 2.1 p.charAt(j-1) != s.charAt(j):例如xxxa 和 xxxb*匹配,这种情况下,只有这两个红框中的内容相同时才匹配得上:
    在这里插入图片描述
    例如
j
qwe
i-2i
qweb*

qwe 和 qweb*可以匹配上,但是qwea和qweb*就匹配不上
此时有dp[i][j]=dp[i-2][j]

  • 2.2 p.charAt(j-1) == s.charAt(j):这种情况在三种条件下是匹配的:
    2.2.1

dp[i-2][j] == True

2.2.2

dp[i-1][j] == True

2.2.3

这种情况下dp[i-1][j]和dp[i-2][j]都为Flase
但此时有dp[i][j-1] == True

即在情况2.2下,有:
dp[i][j] = dp[i-1][j] || dp[i-2][j] || dp[i][j-1]


提交代码
class Solution {
    public boolean isMatch(String s, String p) {
    	if(s==null||p==null)	return false;
    	int n=s.length(),m=p.length();
    	Boolean[][] dp=new Boolean[m+1][n+1];
    	
    	for(int i=0;i<=m;i++)
    		for(int j=0;j<=n;j++)
    			dp[i][j]=false;
    	
    	dp[0][0] =true;
    	for(int i=1;i<=m;i++) {
    		if(i%2==0) 	dp[i][0]=((p.charAt(i-1)=='*')&&dp[i-2][0]);
    		else	dp[i][0]=false;
    	}
    	for(int j=1;j<=n;j++)
    		dp[0][j]=false;
    	
    	for(int i=1;i<=m;i++) {
    		for(int j=1;j<=n;j++) {
    			if(s.charAt(j-1)==p.charAt(i-1)||p.charAt(i-1)=='.')
    				dp[i][j]=dp[i-1][j-1];
    			else if(p.charAt(i-1)=='*') {
    				if(p.charAt(i-2)!=s.charAt(j-1)&&p.charAt(i-2)!='.')
    					dp[i][j]=dp[i-2][j];
    				else {
    					dp[i][j]=dp[i-1][j]||dp[i-2][j]||dp[i][j-1];
    				}
    			}
    		}
    	}
    	return dp[m][n];
    }
}

####运行结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值