解题框架:【README1】动态规划之解题思路

文章目录

  • 题目
  • 解题思路
  • 动态规划
  • CODE

题目

LeetCode10:正则表达式匹配

解题思路

正则表达式的匹配规则我在这里就不多说了,相信大家都很清楚。
本题会给出两个字符串spp代表的是模式串,也就是带有正则表达式的那个字符串,判断p是否可以匹配字符串s

.号很好实现,遇到它直接匹配就可。难点就在于*,因为一旦出现 *号,它前面的字符可以出现1次,也可以出现n次,也可以不出现。比如.a*b就可以匹配zaaab

关于字符串的撇匹配,大家首先想到的肯定是两个指针:ij分别在sp上移动,如果他们都能移动到各自的字符串末尾,则匹配成功,否则失败


所以如果我们先不要考虑*,代码就能很容易写出来

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],那么

  1. p[j]有可能匹配多个字符,比如当s="aaa",p="a*"时,就匹配了3次
  2. 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次还是多次 。那么既然属于动态规划的题目,因此这个问题就需要用到咋们之前讲到过的思想来解决了。

  1. 状态是什么?自然是i和j的位置
  2. 选择是什么?自然就是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)

  1. j+2i不变就是直接跳过p[j]和后面的通配符,即匹配了0次

  2. 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决定了程序何时退出,以及退出的结果是否正确。

  1. 如果j==p.size(),也就是p串走完,那么此时如果i也等于s.size(),就表示匹配成功
  2. 但是如果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()时,去除掉一些干扰情况

  1. 如果i==size(),那么对于p来说,其中的字符和*一定是成对出现的
  2. 上面成对出现有一种非常奇葩的情况,就是通配符出现字母前,这样是无法匹配的,因此要把这种情况给剔除掉

判断的代码如下

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);}
};

动态规划之正则表达式匹配字符串相关推荐

  1. python正则匹配字符串中的数字_Python正则表达式匹配字符串中的数字

    1.使用"\d+"匹配全数字 代码: import re zen = "Arizona 479, 501, 870. Carlifornia 209, 213, 650. ...

  2. python正则匹配11个数字_Python正则表达式匹配字符串中的数字

    导读 这篇文章主要介绍了Python正则表达式匹配字符串中的数字,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 1.使用"\d+"匹配全数字 ...

  3. python正则表达式匹配字符串中的电话号码_Python正则表达式匹配字符串中的数字...

    这篇文章主要介绍了Python正则表达式匹配字符串中的数字,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 1.使用"\d+"匹配全数字 代码: ...

  4. Python正则表达式匹配字符串中的数字

    导读 这篇文章主要介绍了Python正则表达式匹配字符串中的数字,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 1.使用"\d+"匹配全数字 ...

  5. 正则表达式匹配字符串(scala)

    正则表达式匹配字符串 代码 import scala.util.matching.Regexobject RegDemo extends App{//构建正则表达式//方式一val pattern1= ...

  6. 正则表达式匹配字符串中以数字结尾的字符

    正则表达式匹配字符串中以数字结尾的字符 <li class="xxx"><a href="http://www.xxx.net/abc90.htm&qu ...

  7. C#中使用正则表达式匹配字符串

    C#中使用正则表达式匹配字符串的方法如下: 1.使用System.Text.RegularExpressions命名空间: 2.使用Matches()方法匹配字符串,格式如下: MatchCollec ...

  8. python-利用正则表达式匹配字符串

    python正则表达式相关的模块是re 该模块有几个常用的方法 re.compile() 生成一个正则对象 re.match().group() 根据正则表达式匹配字符串,如果不是从字符串首位匹配的, ...

  9. python正则表达式匹配字符串相关方法

    python正则表达式匹配字符串相关方法 一.匹配方法简要介绍及注意事项 1.贪婪匹配与非贪婪匹配 2.findall与search的选取问题 3.匹配时"()"和"[] ...

最新文章

  1. Session对象失效的客户端解决方法
  2. string转int 等(转)
  3. 开源Android容器化框架Atlas开发者指南
  4. matlab获取标量
  5. Oracle编程入门经典 第1章 了解Oracle
  6. 简明扼要的反射入门教程
  7. 互联网晚报 | 11月20日 星期六 | 阿里云单季营收首次超200亿;淘特年度活跃用户超2.4亿;首届中国网络文明大会在京召开...
  8. QT Embedded二三事之QObject的元对象
  9. F: 绝对值 山东科技大学OJ C语言
  10. yii2 html编辑器,浅析Yii2集成富文本编辑器redactor实例教程
  11. 横向比较图像标注中的两种基于近邻思想的方法 TagProp和SGSSL
  12. 为什么blender安装后无法打开_CAD软件打开图纸后钢筋符号无法读取的解决办法...
  13. 简单介绍会计师事务所
  14. java Short详解
  15. bpftrace 段错误 bpf_prog_load_deprecated
  16. 婚宴座位图html5,20桌婚宴座位安排图(婚宴座位顺序如何安排?)
  17. 凉宫春日的忧郁第一章
  18. ADI的DSP,Blackfin系列中最受欢迎的型号:BF533
  19. android打电话 接电话 挂电话流程分析
  20. 脉冲当量与电子齿轮比疑惑

热门文章

  1. centos linux下vnc server远程桌面配置详解,CentOS 6.0 VNC远程桌面配置
  2. 查找最接近的元素c语言,查找最接近的元素
  3. Pycharm的git密码填错了的修改方法
  4. 微信小程序消息推送自有服务器无法接收到信息,消息推送服务器配置次数用完的解决方式。
  5. STM32H743+Cube-Keil上移植RTX5实时系统
  6. python去重复字符串_python3取出重复3次的字符串保存为3列
  7. PHP笔记-连接MySQL数据库及查询数据
  8. Web前端笔记-element ui中table中某列添加a便签进行跳转
  9. Qt文档阅读笔记-QHeaderView::sectionResized官方解析与实例
  10. Linux工作笔记-查看tcp与udp端口并对比Windows简单分析