动态规划之正则表达式匹配字符串
解题框架:【README1】动态规划之解题思路
文章目录
- 题目
- 解题思路
- 动态规划
- CODE
题目
LeetCode10:正则表达式匹配
解题思路
正则表达式的匹配规则我在这里就不多说了,相信大家都很清楚。
本题会给出两个字符串s
和p
,p
代表的是模式串,也就是带有正则表达式的那个字符串,判断p是否可以匹配字符串s
.
号很好实现,遇到它直接匹配就可。难点就在于*
,因为一旦出现 *
号,它前面的字符可以出现1次,也可以出现n次,也可以不出现。比如.a*b
就可以匹配zaaab
关于字符串的撇匹配,大家首先想到的肯定是两个指针:i
和j
分别在s
和p
上移动,如果他们都能移动到各自的字符串末尾,则匹配成功,否则失败
所以如果我们先不要考虑*
,代码就能很容易写出来
bool isMatch(string s,string p)
{int i,j=0;while(i<s.size() && j<p.size()){if(s[j]==s[j] || p[j]=='.'){i++;j++;}else return false;}return true;
}
如果p[j+1]
为通配符*
,则考虑的情况较多,主要分为以下两种
1:如果s[i]==p[j]
,那么
p[j]
有可能匹配多个字符,比如当s="aaa",p="a*
"时,就匹配了3次p[j]
也有可能匹配0个字符,比如当s="aa",p="a*aa"
,可以发现匹配了0次
2:如果s[i]!=p[j]
,那么
p[j]
只能匹配0次,然后看p的下一个字符是否能和s[i]
匹配。比如s="aa",p="b*aa"
于是我们可以写出伪代码如下
if(s[i]==p[j] || p[j]=='.')
{if(j<p.size()-1 && p[j+1]=='*'){//有通配符*可以匹配0次或多次}else{//没有通配符*只能匹配1次i++;j++;}
}
else
{if(j<p.size()-1 && p[j+1]=='*'){//有通配符*可以,只能匹配0次}else{//没有通配符直接失败return false;}
}
代码的思路很清晰了,看起来的确很简单,那么为什么这道题难度还是hard呢?其实问题就在于*
应该匹配0次还是多次 。那么既然属于动态规划的题目,因此这个问题就需要用到咋们之前讲到过的思想来解决了。
- 状态是什么?自然是i和j的位置
- 选择是什么?自然就是
p[j]
,也即是*
应该匹配几个字符
动态规划
根据以上描述,首先按照暴力解法思想,先定义一个dp函数,如下
bool dp(string& s,int i,string& p,int j)
如果该函数返回值为true,表示可以匹配,反之不可以
bool isMathch(string s,string p)
{return dp(s,0,p,0);
}bool dp(string& s,int i,string& p,int j)
{if(s[i]==p[j] || p[j]=='.'){if(j<p.size()-1 && p[j+1]=='*'){//1:可以匹配0次,或者多次return dp(s,i,p,j+2) || dp(s,i+1,p,j);}else{//:2:只能匹配1次return dp(s,i+1,p,j+1);}}else{if(j<p.size()-1 && p[j+1]=='*'){//3:只能匹配0次,看下面有没有相等的return dp(s,i,p,j+2);}else{//4:无法匹配return false;}}
}
上述代码中,注释中的解释分别如下
1:可以匹配0次,或者多次:return dp(s,i,p,j+2) || dp(s,i+1,p,j)
j+2
,i
不变就是直接跳过p[j]和后面的通配符,即匹配了0次
i+1
,j不变,就是p[j]已经匹配了s[i]
,但是p[j]
还可以匹配s[i]
后面的,也就是匹配多次
2:只能匹配1次:return dp(s,i+1,p,j+1
),这种情况就不多做解释了
3:只能匹配0次,看下面有没有相等的:return dp(s,i,p,j+2)
- 这种情况和情况1中的第一种类似,也就是匹配0次
4:最后一种情况就是失败
最后需要处理一个棘手的问题,就是base case,因为base case决定了程序何时退出,以及退出的结果是否正确。
- 如果
j==p.size()
,也就是p串走完,那么此时如果i
也等于s.size()
,就表示匹配成功 - 但是如果
i=p.size()
,是不能通过判断是否j==p.size()
的方式来判断是否成功的。因为可能会出现s="a",p=“ab*c*
”这种情况,可以发现虽然p
没有走完,但是它仍然是匹配的。
所以我们的思路是,首先if(j==p.size())
,那么就return i==s.size()
,如果此时i
还等于s.size()
,一定成功。
另一个重点就是i==size()
时,去除掉一些干扰情况
- 如果
i==size()
,那么对于p
来说,其中的字符和*
一定是成对出现的
- 上面成对出现有一种非常奇葩的情况,就是通配符出现字母前,这样是无法匹配的,因此要把这种情况给剔除掉
判断的代码如下
if(i==s.size())
{if(p.size()-j)%2!=0){return false;}for(;j<p.size();j+=2){if(p[j+1]!='*'){return false;}}return true;
}
CODE
至此我们就可以写出完整的代码了
class Solution {public:bool dp(string& s,int i,string& p,int j,unordered_map<string,bool>& memory){if(j==p.size())//如果p串匹配完了return i==s.size();//看s串的情况if(i==s.size()){if((p.size()-j)%2==1)//*和字符未成对出现return false;for(;j+1<p.size();j+=2)//防止出现x和x*y*z*的情况{if(p[j+1]!='*')return false;}return true;}//消除重叠问题string key=to_string(i)+","+to_string(j);if(memory.count(key))return memory[key];bool res=false;if(s[i]==p[j] || p[j]=='.'){if(j<p.size()-1 && p[j+1]=='*'){res=dp(s,i,p,j+2,memory) || dp(s,i+1,p,j,memory);}else{res=dp(s,i+1,p,j+1,memory);} }else{if(j<p.size()-1 && p[j+1]=='*'){res=dp(s,i,p,j+2,memory);}else{res=false;}}memory[key]=res;return res;}bool isMatch(string s, string p) {unordered_map<string,bool> memory;return dp(s,0,p,0,memory);}
};
动态规划之正则表达式匹配字符串相关推荐
- python正则匹配字符串中的数字_Python正则表达式匹配字符串中的数字
1.使用"\d+"匹配全数字 代码: import re zen = "Arizona 479, 501, 870. Carlifornia 209, 213, 650. ...
- python正则匹配11个数字_Python正则表达式匹配字符串中的数字
导读 这篇文章主要介绍了Python正则表达式匹配字符串中的数字,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 1.使用"\d+"匹配全数字 ...
- python正则表达式匹配字符串中的电话号码_Python正则表达式匹配字符串中的数字...
这篇文章主要介绍了Python正则表达式匹配字符串中的数字,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 1.使用"\d+"匹配全数字 代码: ...
- Python正则表达式匹配字符串中的数字
导读 这篇文章主要介绍了Python正则表达式匹配字符串中的数字,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 1.使用"\d+"匹配全数字 ...
- 正则表达式匹配字符串(scala)
正则表达式匹配字符串 代码 import scala.util.matching.Regexobject RegDemo extends App{//构建正则表达式//方式一val pattern1= ...
- 正则表达式匹配字符串中以数字结尾的字符
正则表达式匹配字符串中以数字结尾的字符 <li class="xxx"><a href="http://www.xxx.net/abc90.htm&qu ...
- C#中使用正则表达式匹配字符串
C#中使用正则表达式匹配字符串的方法如下: 1.使用System.Text.RegularExpressions命名空间: 2.使用Matches()方法匹配字符串,格式如下: MatchCollec ...
- python-利用正则表达式匹配字符串
python正则表达式相关的模块是re 该模块有几个常用的方法 re.compile() 生成一个正则对象 re.match().group() 根据正则表达式匹配字符串,如果不是从字符串首位匹配的, ...
- python正则表达式匹配字符串相关方法
python正则表达式匹配字符串相关方法 一.匹配方法简要介绍及注意事项 1.贪婪匹配与非贪婪匹配 2.findall与search的选取问题 3.匹配时"()"和"[] ...
最新文章
- Session对象失效的客户端解决方法
- string转int 等(转)
- 开源Android容器化框架Atlas开发者指南
- matlab获取标量
- Oracle编程入门经典 第1章 了解Oracle
- 简明扼要的反射入门教程
- 互联网晚报 | 11月20日 星期六 | 阿里云单季营收首次超200亿;淘特年度活跃用户超2.4亿;首届中国网络文明大会在京召开...
- QT Embedded二三事之QObject的元对象
- F: 绝对值 山东科技大学OJ C语言
- yii2 html编辑器,浅析Yii2集成富文本编辑器redactor实例教程
- 横向比较图像标注中的两种基于近邻思想的方法 TagProp和SGSSL
- 为什么blender安装后无法打开_CAD软件打开图纸后钢筋符号无法读取的解决办法...
- 简单介绍会计师事务所
- java Short详解
- bpftrace 段错误 bpf_prog_load_deprecated
- 婚宴座位图html5,20桌婚宴座位安排图(婚宴座位顺序如何安排?)
- 凉宫春日的忧郁第一章
- ADI的DSP,Blackfin系列中最受欢迎的型号:BF533
- android打电话 接电话 挂电话流程分析
- 脉冲当量与电子齿轮比疑惑
热门文章
- centos linux下vnc server远程桌面配置详解,CentOS 6.0 VNC远程桌面配置
- 查找最接近的元素c语言,查找最接近的元素
- Pycharm的git密码填错了的修改方法
- 微信小程序消息推送自有服务器无法接收到信息,消息推送服务器配置次数用完的解决方式。
- STM32H743+Cube-Keil上移植RTX5实时系统
- python去重复字符串_python3取出重复3次的字符串保存为3列
- PHP笔记-连接MySQL数据库及查询数据
- Web前端笔记-element ui中table中某列添加a便签进行跳转
- Qt文档阅读笔记-QHeaderView::sectionResized官方解析与实例
- Linux工作笔记-查看tcp与udp端口并对比Windows简单分析