《剑指offer》——正则表达式匹配

60 篇文章 3 订阅

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

T:

题目描述:
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配

前两天刚看了有关正则表达式的基本语法和用法,今天刷牛客,就恰好碰到了这个题。
题目的解决思路,最方便的方式就是递归。不用递归,整个的处理流程以及要分类讨论的情况会比较复杂。

根据题目的描述,最直观的一点,就是如何处理字符’.‘和’*‘在一起的情形,即’.*’。

不管以何种方式进行递归,总归是要从字符串和模式的最左侧开始。设置如下递归函数:

    isMatch(char[] str, int indexStr, char[] pattern, int indexPat){...}

该递归函数的含义为:对于从 i n d e x S t r indexStr indexStr下标开始的字符串 s t r str str,和从 i n d e x P a t indexPat indexPat下标开始的模式 p a t t e r n pattern pattern,两者的右侧部分能否匹配。

对于带有’*'的情况,有以下3种情况:
这里写图片描述

对于前两种,在匹配时,可以有以下匹配方式:
这里写图片描述
其中,匹配多次,指的是上面的a后面的内容,也用下面的两个字符’.'或者’a’去匹配。

对于第三种情况,‘a’对应的’b*’,这个时候可以直接忽略’b*’,即匹配0次。

贴上代码:

    /**
 * T: 正则表达式匹配
 * 请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 
 * 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
 * 
 * date: 2016.5.20
 * @author SSS
 *
 */
public class Solution {

	public boolean match(char[] str, char[] pattern) {
		
		return this.isMatch(str, 0, pattern, 0);
	}
	
	/**
	 * 递归实现
	 * @param str
	 * @param indexStr
	 * @param pattern
	 * @param indexPat
	 * @return
	 */
	public boolean isMatch(char[] str, int indexStr, char[] pattern, int indexPat) {
		// 两者都达到了最后,说明已经完全匹配
		if (indexStr == str.length && indexPat == pattern.length) {
			return true;
		}
		// 模板的index已经超出自身长度,那么就是不匹配的
		if (indexPat >= pattern.length) {
			return false;
		}
		
		// 考虑pattern中包含‘*’的情况
		if (indexPat < pattern.length - 1 && pattern[indexPat + 1] == '*') {
			if (indexStr < str.length && (str[indexStr] == pattern[indexPat] || pattern[indexPat] == '.')) {
				return isMatch(str, indexStr, pattern, indexPat + 2) || isMatch(str, indexStr + 1, pattern, indexPat + 2) || isMatch(str, indexStr + 1, pattern, indexPat);
			} else { // indexStr达到了末尾,但是indexPat没达到末尾,另外,对于str中的a,可能pattern中跟的是b*
				return isMatch(str, indexStr, pattern, indexPat + 2);
			}
		}
		
		
		if (indexStr == str.length) {
			return false;
		}
		
		if (str[indexStr] == pattern[indexPat] || pattern[indexPat] == '.') {
			return isMatch(str, indexStr + 1, pattern, indexPat + 1);
		}
		
		return false;
	}
	
    //	public static void main(String []args) {
    //		char[] str = {'a', 'd', 'b', 'c', 'b', 'd'};
    //		char[] pattern = {'a', '.', '*', 'b', '.', '*', 'd', '*'};
    //		Solution1 solution1 = new Solution1();
    //		System.out.println(solution1.match(str, pattern));
    //	}
}

其中,本方法也不算是我独自想出来的,参考了讨论区里面大牛的做法,本方法算是理解之后,依葫芦画瓢得到的。

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值