剑指offer:正则表达式匹配
时间:2019-03-15
本文章向大家介绍剑指offer:正则表达式匹配,主要包括剑指offer:正则表达式匹配使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目
题目链接
剑指offer:正则表达式匹配
题目描述
请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符.
表示任意一个字符,而*
表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。
解题思路
1.分析题目
- 输入:一个待匹配字符串,一个待匹配正则表达式
- 输出:字符串与正则表示式相匹配则输出
true
,否则输出false
- 条件:正则表达式中仅含两个特殊字符;
.
表示任意一个字符,*
表示它前面的字符能够出现0~无数次。题目未说明是否贪心匹配(即尽可能多的匹配)的情况下,应默认非贪心匹配。即应考虑类似aaa
与a*aa
相匹配的情况。同时注意可能会出现.*
这类能够匹配所有字符的表达式。
2.可能出现的情况
考虑字符串和正则相匹配时能够相消去,则当最终两者为空时为匹配成功;中途有不匹配且不带*的字符或是最终不能相互消去时为匹配失败。这种情况很显然使用指针移动特别好用。
考虑情况如下:
- 字符串空时,正则式不为空。后者剩余字符若皆为带/*字符,则应继续消去。
- 当前指针指向字符能够消去时(正则式当前指针字符与字符串当前指针字符相同,或是正则式当前指针字符为
.
且字符当前指针不为\0
),需要考虑正则指针的下一步指向是否为*
。为*
则需要考虑此时是否非贪心匹配。 - 当前指针指向字符不可相互消去时,需考虑正则指针下一步指向是否为
*
,为*
则可忽略正则指针此时的不匹配字符,令其向前移两位;否则直接匹配失败。例如aaa
与ab*c*aa
能匹配成功。
3.思考解题步骤
在2中所考虑的情况都能够用起初的思路--指针移动解决,故确定以指针为解题方向。
同时,每一步对于当前指针指向字符的处理过程都是相似的,故考虑使用递归使代码更加简洁。
很惭愧,在编写2中指针字符相互消去的情况时,我发现自己写的代码总是会遗漏部分情况,查看错误样例后发现对*
的非贪心匹配处理要写出大量逻辑繁琐且容易出错的代码。在查看讨论区的解答后,发现自己一直走了死胡同。对于这种问题应考虑使用动态规划的思想,将情况一分为二的处理,分别计算继续判断当前*
与结束当前*
匹配的情况。
具体代码
原答案中需要同时判断一分为二后的两种情况,在这里我做出了一些细微改进,优先判断跳过*
的情况。
class Solution {
public:
bool match(char* str, char* pattern)
{
if (*str == '\0' && *pattern == '\0')
return true;
// 1.匹配带*正则(包括非贪心情况)
if (*str == *pattern || (*pattern == '.' && *str != '\0'))
{
// 不是正则式
if (*(pattern + 1) != '*')
return match(++str, ++pattern);
// 是正则式
// 将*字符的匹配一分为二的处理
// 讨论中是:return match(str, pattern) || match(str, pattern + 2);
if (match(str, pattern + 2)) // 跳过当前*,即匹配正则中下一个字符
return true;
return match(str + 1, pattern); // 继续匹配当前*
}
// 消去无用带*字符
else if (*(pattern + 1) == '*')
{
pattern += 2;
return match(str, pattern);
}
return false;
}
};
- HDUOJ----A Computer Graphics Problem
- HDUOJ---(4708)Herding
- HDUOJ---(4708)Rotation Lock Puzzle
- HDUOJ---Hamming Distance(4712)
- HDUOJ-----Difference Between Primes
- HDUOJ----(4706)Children's Day
- poj-------Common Subsequence(poj 1458)
- poj----Maximum sum(poj 2479)
- HDUOJ---hello Kiki
- HDUOJ-----X问题
- POJ-----C Looooops
- POJ--Strange Way to Express Integers
- HDUOJ----More is better(并查集)
- HDUOJ 1099——Lottery
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- RecyclerView+PagerSnapHelper实现抖音首页翻页的Viewpager效果
- android中使用react-native设置应用启动页过程详解
- 面试官问我单例模式真的安全吗?我懵逼了
- 详解Android使用CoordinatorLayout+AppBarLayout实现拉伸顶部图片功能
- Android自定义控制条效果
- Android使用MediaPlayer和TextureView实现视频无缝切换
- Android实现静默拍照功能
- Android实现动态体温计
- Android实现倾斜角标样式
- 浅谈Flutter 中渐变的高级用法(3种)
- Android实现左上角(其他边角)倾斜的标签(环绕效果)效果
- Android开发中Button组件的使用
- Android开发之基于RecycleView实现的头部悬浮控件
- Android如何通过命令行操作Sqlite3数据库的方法
- Android实现沉浸式状态栏功能