引言:这道题情况比较复杂,边界条件较多,为了便于以后复习,整理一下。另外,由于C语言和Java对于字符串的操作存在不一样的地方,代码也存在改动。

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

分析:这道题的核心其实在于分析'*',对于'.'来说,它和任意字符都匹配,可把其当做普通字符。对于'*'的分析,我们要进行分情况讨论,当所有的情况都搞清楚了以后,就可以写代码了。

在每轮匹配中,Patttern第二个字符是'*'时:

  1. 第一个字符不匹配('.'与任意字符视作匹配),那么'*'只能代表匹配0次,比如'ba'与'a*ba',字符串不变,模式向后移动两个字符,然后匹配剩余字符串和模式
  2. 第一个字符匹配,那么'*'可能代表匹配0次,1次,多次,比如'aaa'与'a*aaa'、'aba'与'a*ba'、'aaaba'与'a*ba'。匹配0次时,字符串不变,模式向后移动两个字符,然后匹配剩余字符串和模式;匹配1次时,字符串往后移动一个字符,模式向后移动2个字符;匹配多次时,字符串往后移动一个字符,模式不变;

而当Patttern第二个字符不是'*'时,情况就简单多了

  1. 如果字符串的第一个字符和模式中的第一个字符匹配,那么在字符串和模式上都向后移动一个字符,然后匹配剩余字符串和模式。
  2. 如果字符串的第一个字符和模式中的第一个字符不匹配,那么直接返回false。

好,现在思路已经清楚了,可以看代码了:

 package test;
import java.util.Scanner; public class Question_53 {
public static boolean match(String input,String pattern){
if(input==null||pattern==null) return false;
return matchCore(input,0,pattern,0);
}
private static boolean matchCore(String input,int i,String pattern,int p){
if((input.length()==i)&&(pattern.length()==p)){
//出口1,input和pattern都到了字符串末尾
return true;
}
if((i!=input.length())&&(pattern.length()==p)){
//出口2,字符串input没有到末尾,pattern到了末尾
return false;
}
if((input.length()==i)&&(pattern.length()!=p)){
//出口3,字符串input到末尾,pattern还没有到末尾
return false;
} if((p+1<pattern.length())&&(pattern.charAt(p+1)=='*')){//pattern第二个字符为*
if((input.charAt(i)==pattern.charAt(p))||(pattern.charAt(p)=='.')){
//首字母相匹配
return matchCore(input,i+1,pattern,p+2) //*表示出现1次
||matchCore(input,i+1,pattern,p) //*表示出现多次
||matchCore(input,i,pattern,p+2); //*表示出现0次 , a ... p* ...
}else{
//首字母不匹配
return matchCore(input,i,pattern,p+2);
}
} //end pattern.charAt(p+1)=='*' if((input.charAt(i)==pattern.charAt(p))||(pattern.charAt(p)=='.')){
//pattern第二个字母不是*,且首字母匹配
return matchCore(input,i+1,pattern,p+1);
}
return false; //其余情况全部不匹配
} public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in); //扫描键盘输入
System.out.println(" 请输入第一个字符串:");
String str1 = scanner.nextLine();
System.out.println(" 请输入第二个字符串:");
String str2 = scanner.nextLine();
scanner.close(); System.out.print("匹配的结果为:");
System.out.println(match(str1, str2));
} }

注意边界条件,当模式和字符串都只剩一个字符时, pattern.charAt(p+1)=='*' 会访存越界,所以需要加额外的限制条件 p+1<pattern.length() ,这样这个条件不能满足就会进入下一个if判断语句,直接判断两个字符是不是相等,最后进入出口1,返回true。字符串和模式任意一个先结束都视作不匹配,返回false,这就是出口2和出口3.

《剑指offer》 面试题53 :正则表达式匹配 Java的更多相关文章

  1. 【剑指Offer】52、正则表达式匹配

      题目描述:   请实现一个函数用来匹配包括'.'和'*'的正则表达式.模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配是指字符串的所有字符匹 ...

  2. 剑指Offer:面试题34——丑数(java实现)

    问题描述: 把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7. 习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第N个丑数. 思路1: ...

  3. 剑指Offer:面试题16——反转链表(java实现)

    问题描述 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点.链表结点如下: public class ListNode { int val; ListNode next = n ...

  4. 剑指Offer:面试题15——链表中倒数第k个结点(java实现)

    问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...

  5. 剑指offer面试题3 二维数组中的查找(c)

    剑指offer面试题三:

  6. 剑指Offer——笔试题+知识点总结

    剑指Offer--笔试题+知识点总结 情景回顾 时间:2016.9.23 12:00-14:00 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:笔试 注意事项:要有大局观, ...

  7. C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告

    剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...

  8. C++版 - 剑指offer 面试题23:从上往下打印二叉树(二叉树的层次遍历BFS) 题解

    剑指offer  面试题23:从上往下打印二叉树 参与人数:4853  时间限制:1秒  空间限制:32768K 提交网址: http://www.nowcoder.com/practice/7fe2 ...

  9. C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解

    剑指offer 面试题39:判断平衡二叉树 提交网址:  http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...

  10. Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)

    剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...

随机推荐

  1. 20162327WJH第二次实验——树

    20162327WJH第一次实验--线性结构 实 验 报 告 实 验 报 告 课程:程序设计与数据结构 班级: 1623 姓名: 王旌含 学号:20162327 成绩: 指导教师:娄嘉鹏 王志强 实验 ...

  2. NABCD模型分析

    1.N——need需求 目前,学习英语是所有学生会面临的问题.提高词汇量对学习英语是十分必要的,尤其是对大学生来说对手机的使用特别频繁,我们提高英语词汇量也应该把手机更好的利用起来,利用自己对手机的使 ...

  3. 寒假作业第二篇随笔(A+B)

    Github链接:https://github.com/heihuifei/object-oriented A+B Format (20) Calculate a + b and output the ...

  4. C++第一次作业

    Github地址点这里

  5. Java分布式应用

    分布式计算就是通过计算机网络将计算工作分布到多台主机上,多个主机一起协同完成工作. 我试着列一下相关知识吧. 网络通讯,网络是分布式的基础,对分布式的理解建立在对网络的理解上,包括: OSI模型的7层 ...

  6. es6箭头函数的注意要点

    具有一个参数的简单函数 var single = a => a single('hello, world') // 'hello, world' 没有参数的需要用在箭头前加上小括号 var lo ...

  7. MySQL的间隙锁

    什么是间隙锁当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁:对于键值在条件范围内但不存在的记录,叫做“间隙(GAP)”,InnoDB也 ...

  8. spring的jar包以及相关的API文档的下载方式

    转自:http://blog.csdn.net/yuexianchang/article/details/53583327 侵删 感谢原创 首先是进入官网:https://spring.io/ 如图所 ...

  9. AtCoder Grand Contest 029 翻车记

    A:对于每个B,会和其右边的每个W交换一次. #include<iostream> #include<cstdio> #include<cmath> #includ ...

  10. ava8并发教程:Threads和Executors

    原文地址  原文作者:Benjamin Winterberg 译者:张坤 欢迎阅读我的Java8并发教程的第一部分.这份指南将会以简单易懂的代码示例来教给你如何在Java8中进行并发编程.这是一系列教 ...