leetcode hard模式专杀之10Regular Expression Matching

本文介绍了一种解决正则表达式匹配问题的算法实现,采用递归与动态规划相结合的方法,通过剪枝减少不必要的计算,并提供了一段Java代码示例。

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

我觉得这个问题思路基本上跟八皇后问题属于一大类,用回溯法or用动态规划去做,而所谓动态规划也无非就是对暴力破解进行剪枝,把哪些重复的计算去掉,话虽这么说,如果真在面试时碰到这种题目,那基本上还是等死吧。

写起来可以分两部,先把暴力的递归写出来,确保程序能work,然后再在暴力递归的基础上做去重,这样就可以进化出能通过oj的最终结果

递归的思路如下:

假如有s=aaab和p=a*b(肉眼一看就知道匹配true)

则其中a*可以匹配a, aa, aaa, 但是千万注意别漏掉a匹配0个字符串的情况,也就是说,即使a*b变成c*a*b,依然为true

而对这四种情况,规模降级后的子函数可以认为是 匹配 (aaab, b), (aab, b), (ab, b), (b, b)

也就是说pattern降级为a*后面的子串, 而原字符串降级为前面已匹配的字符串扣除后的右边剩下的字符串。递归的思路就是这样。


而去重的思路可以这样描述, 因为这里的所谓剩余的右边的字串,可以形式化地用原始字符串s和一个index来标识,例如ab, 可以用aaab和2来标示, aab可以用aaab和1来标识,总之一切都是为了形式化一个递归函数,那么有了这种标示方法后,就可以建立一个二维数组,arr[][], arr[i][j]用来表示  原始字符串从i开始的子串和原始pattern从j开始的子串是否匹配, 如果匹配用1表示,不匹配用0表示,而为了防止数组溢出,可以在s.length()以及p.length()的基础上分别加1,作为这个数组的维度。


思路基本就是这样,下面上java代码:


package javatest;

public class RegularExpressionMatching {
	public static boolean isMatch(String s, String p) {
		int[][] arr = new int[s.length()+1][p.length()+1];
		return innerisMatch(s,p,0,0,arr);
	}
	
	public static boolean innerisMatch(String s, String p, int indexs, int indexp, int[][] repo) { 
		//	System.out.println(innerisMatch("aa","a"));  //false
		//	System.out.println(innerisMatch("aa","aa"));  //true
		//	System.out.println(innerisMatch("aaa","aa"));  //false
		//	System.out.println(innerisMatch("aa","a*"));  //true
		//	System.out.println(innerisMatch("aa",".*"));  //true
		//	System.out.println(innerisMatch("ab",".*"));  //true
		//	System.out.println(innerisMatch("aab","c*a*b"));  //true

		// avoid duplicate calculation
		if(indexs > s.length()){
			return false;
		}
		
		if(repo[indexs][indexp]==1){
			return true;
		}
		
		if(s==null || p==null){
			return false;
		}

		if(s.substring(indexs, s.length()).length() == 0 && p.substring(indexp, p.length()).length() == 0){
			repo[indexs][indexp]=1;
			return true;
		}

		if(p.substring(indexp, p.length()).length()==0){
			return false;
		}

		if(p.charAt(indexp)=='.'){
			if(p.substring(indexp, p.length()).length()>1 && p.charAt(indexp+1)=='*'){
				int si=0;
				while(si<s.substring(indexs, s.length()).length()){
					if(innerisMatch(s,p,indexs+si,indexp+2,repo)){
						repo[indexs][indexp]=1;
						return true;
					}
					si++;
				}
				if(innerisMatch(s,p,indexs+si, indexp+2, repo)){
					repo[indexs][indexp]=1;
					return true;
				}else{
					return false;
				}
			}else{
				
				if(innerisMatch(s, p, indexs+1, indexp+1, repo)){
					repo[indexs][indexp]=1;
					return true;
				}else{
					return false;
				}
			}
		}else if(p.charAt(indexp)=='*'){
			if(innerisMatch(s, p, indexs, indexp+1, repo)){
				repo[indexs][indexp]=1;
				return true;
			}else{
				return false;
			}
		}else{
			if(p.substring(indexp, p.length()).length()>1 && p.charAt(indexp+1)=='*'){
				int si = 0;
				if(indexs<s.length() &&  s.charAt(indexs)==p.charAt(indexp) ){
					while(si<s.substring(indexs,s.length()).length() && s.charAt(indexs+si)==s.charAt(indexs)){
						
						if(innerisMatch(s, p, indexs+si, indexp+2, repo )){
							repo[indexs][indexp]=1;
							return true;
						}
						si++;
					}
					if(innerisMatch(s, p, indexs+si, indexp+2, repo )){
						repo[indexs][indexp]=1;
						return true;
					}else{
						return false;
					}
				}else{
					if(innerisMatch(s,p,indexs,indexp+2,repo)){
                        repo[indexs][indexp]=1;
                        return true;
                    }else{
                        return false;
                    }
				}
			}else{
				if(indexs<s.length() && s.charAt(indexs) == p.charAt(indexp)){
					if(innerisMatch(s, p, indexs+1, indexp+1, repo)){
						repo[indexs][indexp]=1;
						return true;
					}else{
						return false;
					}
				}else{
					return false;
				}
			}
		}
	}

	public static void main(String[] args) throws Exception {
		//test cases
		System.out.println(isMatch("aa","a"));  //false
		System.out.println(isMatch("aa","aa"));  //true
		System.out.println(isMatch("aaa","aa"));  //false
		System.out.println(isMatch("aa","a*"));  //true
		System.out.println(isMatch("aa",".*"));  //true
		System.out.println(isMatch("ab",".*"));  //true
		System.out.println(isMatch("aab","c*a*b"));  //true
		System.out.println(isMatch("ab",".*c"));  //false
		System.out.println(isMatch("a","ab*"));  //true
		System.out.println(isMatch("a",".*..a*"));  //false
		System.out.println(isMatch("a","a*a"));  //true
		System.out.println(isMatch("","b*"));  //true
		
		System.out.println(isMatch("aa","b*a"));  //false
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值