正则表达式匹配(动规)
文章目录
- 题目
- 思路
- 转移方程
- 特征
- 再探 i 和 j
- 代码
题目
请实现一个函数用来匹配包含 .
和 *
的正则表达式。模式中的字符 .
表示任意一个字符,而 *
表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串 aaa
与模式 a.a
和 ab*ac*a
匹配,但与 aa.a
和 ab*a
均不匹配。
来源:力扣(LeetCode)
思路
再一次膜拜大佬 作者:jyd
本文基于大佬的思路做自己的细节解析。
其实动规的难点一直在于“找规律”。(恐怕这也是所有算法题的难点,哈哈)
本题其实就是在考察程序员思考问题的全面性。
转移方程
先建立这道题的转移方程:
用 f[i][j]
代表 s
的前 i
个和 p
的前 j
个能否匹配。
当正则表达式中为 正常字符
和 .
时,问题是很好解决的:
f[i][j]=f[i−1][j−1]
前 i 个 s
和 前 j 个 p
是否匹配还要看 前 i-1 个 s
和 前 j-1 个 p
是否匹配。
难点就在于是 字符 + *
时该怎么处理:
分为将字符看成 出现0次
(也就是不看这两位)和 出现多次
(看这个组合):
- 不看:直接砍掉正则串的后面两个,
f[i][j] = f[i][j-2]
- 看:正则串不动,主串前移一个,
f[i][j] = f[i-1][j]
上面两点,大部分题解已经说的很明白了,但其实又很抽象。我们不妨用例子来看一下:
- 第一种比较好理解 ——
f[i][j] = f[i][j-2]
s=abcd
p=abcde*
将主串的最后一位视为 i
(a),正则串最后一位视为 j
(*)。显而易见两个字符串是完全匹配的。只需要 *
前面的 e
(j-1) 出现0次就可(正则串里面的 d
就是 j-2
)。
- 第二种理解起来可能有点抽象 ——
f[i][j] = f[i-1][j]
s=abccc
p=abc*
此时 i为c
、j为*
,因为 *前面的字符
可以 出现多次,也就是出现1次的递归操作
。因此此时我们做的操作就是:
- 已经知道了
i
是j(也就是*前的字符)
,那么再试着看看i-1
还是不是j
。
也就是原本相互匹配的字符我们不看了(都做-1操作),i
和 j
彼此是匹配的,理应再看 i-1
和 j-1
,但是我们想要 j
多出现几次,因此 j-1
的操作没有执行。这就是下图中,jyd大佬所说的 p[j-2]多出现1次
。
图中总说 s[i-1] p[j-1]
为什么不是直接用 s[i] p[j]
呢?这个问题讲完初始化dp数组首行我们再细说。
特征
弄懂了主要的验证是否匹配的操作,接下来我们需要弄懂一些特例:
首先明晰一点:正则串和主串都是可以为空串的。
- 空主串和空正则是匹配的。
- 非空串和空正则必不匹配。
- 空主串和非空正则,不能直接判定匹配与否。
- 非空串和非空正则,那肯定是需要计算的了。
我们可以根据上面的特征,来初始化dp二维数组。
行代表s,列代表p,dp[0][j] 代表s为空,dp[i][0]代表p为空。
第四点其实就是我们的转移方程。因此我们来详解一下第三点:
当s= '' ''
时,p=a*b*c*
和 p=ab*
前者可以做到和空主串完美匹配,后者却不行。因此我们可以得出以下规律:
因此可以得到初始化dp首行的代码(首列无需做多余更改,空正则除了匹配空主串,其余皆不匹配):
// 初始化dp首行
dp[0][0] = 1;
for(size_t i = 2; i < cols; i += 2){dp[0][i] = dp[0][i-2] && p[i-1] =='*';
}
再探 i 和 j
我读完大佬写的题解的时候其实还是很懵懂的,真正豁然开朗是看了大佬的图解。大佬做图解一直有一手的~
下面结合图解来讲一下我们遗留的问题,dp[i][j]
和与之相对应的 s[i-1] p[j-1]
。
我们借用一下大佬的图来看一下:
我们会发现,前面提到:
- 第一行,也就是下标为0的那行,代表 s 为空串
- 第一列,也就是下标为0的那列,代表 p 为空串
我们是从第二行(下标为1的行)和第二列(下标为1的列)开始保存 s 和 p 的非空部分的
。
因此,举个具体的例子:dp[1][1]其逻辑含义是,保存的值表示 前1个s
和前1个p
是否匹配。在物理上代表 s[0]
和 p[0]
组成的点。因此我们也就不难理解大佬图解中频繁出现的 dp[i][j]
和 s[i-1] p[j-1]
之间的关系了。
代码
class Solution {public:bool isMatch(string s, string p) {int rows = s.size()+1;int cols = p.size()+1;vector<vector<int>> dp(rows, vector<int>(cols, 0));// 初始化dp首行dp[0][0] = 1;for(size_t i = 2; i < cols; i += 2){dp[0][i] = dp[0][i-2] && p[i-1] =='*';}// 动规for(size_t i = 1; i < rows; i++){for(size_t j = 1; j < cols; j++){if(p[j-1] != '*'){if(dp[i-1][j-1] && (s[i-1]==p[j-1] || p[j-1] == '.')){dp[i][j] = 1;}}else{if(dp[i][j-2] || (dp[i-1][j] && (s[i-1] == p[j-2] || p[j-2] == '.'))){dp[i][j] = 1;}}}}return dp[rows-1][cols-1];}
};
正则表达式匹配(动规)相关推荐
- re2正则表达式匹配引擎的c接口版本cre2的中文使用手册
前言 re2 官方地址: https://github.com/google/re2 cre2 官方地址: https://github.com/marcomaggi/cre2 1 基本类型定义 不透 ...
- Oracle正则表达式匹配中文的问题
查资料知道中文Unicode范围是\u4e00 - \u9fa5 可是自己用来正则表达式匹配中文总是用不了Unicode.最简单举例: select regexp_replace('abc秋歌def' ...
- python3 正则表达式 嵌套表格_在Python中使用正则表达式匹配嵌套结构
unutbu.. 14 编辑: falsetru的嵌套解析器,我稍微修改为接受任意正则表达式模式来指定分隔符和项目分隔符,比我原来的re.Scanner解决方案更快更简单: import re def ...
- 剑指offer:面试题19. 正则表达式匹配
题目:正则表达式匹配 请实现一个函数用来匹配包含'. '和'*'的正则表达式.模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次).在本题中,匹配是指字符串的所有字符匹 ...
- 使用正则表达式匹配HTML 下各种title标签
http://www.oschina.net/question/195686_46313 <title>标题</title> <title> 标题 </tit ...
- 刻意练习:LeetCode实战 -- Task18. 正则表达式匹配
背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务.本期训练营采用分类别练习的模式,即选择了五个知识点(数组.链表.字符串.树.贪心算法),每个知 ...
- 通配符?子字符串匹配主字符串次数_突破LeetCode,拿BAT大厂offer之《正则表达式匹配》(动态规划)...
导读:算法哥前面分享了一个<通配符匹配>,有粉丝留言,算法哥你再讲讲leetcode上另一道<正则表达式匹配>,正则表达式匹配这道题是前面通配符匹配的加强版,大家一起来学习吧! ...
- Java算法练习——正则表达式匹配
题目链接 题目描述 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符 '*' 匹配零个或多个前面的那一个元素 所谓匹配,是要 ...
- 正则表达式匹配换行符
正则表达式匹配换行符 一开始没有发现html文档中有很多\n,结果用模式 <table[^>]>.*</table> 得到的table间的数据不正确,根据百度百科,可以看 ...
最新文章
- 如何高效地爬取链家的房源信息(四)
- php lvs,LVS(四)LVS集群DR模式
- 非标自动化企业前十名_非标设备的现状
- http详解 请求报文格式和响应报文格式
- c++实现超声回波包络检测_超声波物位计的选用
- SpringBoot - yml与properties配置文件及bean赋值
- c#使用SHA256算法实现对文件的加密和解密
- javatodo框架中怎么配置路由
- 如何终止运行中的线程
- GlobalMapper20提取点云LAS文件当中的投影信息
- 税务会计实务【15】
- 靠谱的社交app有哪些
- 无线网络优化(家用无线网)
- c51语言访问绝对地址的方法,51单片机绝对地址访问的两种方法
- notifier_chain 内核通知链的学习与使用
- iis php 500 内部服务器错误,服务器_iis的http 500内部服务器错误的解决,iis的http 500内部服务器错误是 - phpStudy...
- 区块链大繁荣背后:我们需要引入「预言机」| 专访DOS团队
- 安卓修改电池容量教程_安卓手机端修改电池电量图标的教程
- 你不知道的颠覆式创新者
- 无法打开模块文件“C:\Users\fkg\AppData\Local\Temp\.NETFramework,Version=v4.5.AssemblyAttributes.vb”系统找不到指定文件
热门文章
- python私有属性怎么定义_Python中定义私有属性的方法是()。
- java ldap 分页_具有从属引用的 LDAP 分页查询未正确处理
- 编译mediastreamer2/ffmpeg/linphone(x86平台)
- java fx 建立窗体,3花式窗体与JavaFX CSS
- 计算机组装与维护实验指导,计算机组装与维护实验指导书.pdf
- arcgis选出点规定范围的面
- 【转】聊聊Linux操作系统中的显示管理器及如何更换
- python可以开发驱动吗_Python机器学习实践:测试驱动的开发方法
- java内存分配和垃圾回收,Java内存分配与垃圾回收
- 【Python学习】win10+Anaconda3环境,安装phthon第三方库Jieba