LeetCode 010 Regular Expression Matching

题目大意是匹配一个阉割版的正则表达式。’.’表示匹配任何字符,’*’表示匹配0个或任意个’*’之前的字符。设s是要匹配的字符串,长度为m;设p是模式串,长度为n。

下面的例子是题目中给出的。

isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true

开始我还把题目看错了,我以为*就是和命令行下的*一个意思,匹配任意个字符。结果看到isMatch(“aab”, “c*a*b”) → true还纳闷了半天。

拿到题目先想到贪心法,即看到*的时候就匹配尽量多的字符,但是不对。假设我们有aaaaaaaaa和a*a。用贪心法在遇到第一个*的时候就把a全匹配完了,模式串中剩下一个a没地方匹配了。

一个暴力的方法就是回溯搜索了,从多到少尝试*能匹配的字符。但是显然时间复杂度太高了。极端情况要枚举O(m^n)种情况。回溯为什么慢?因为回溯重复计算了状态树中的节点,状态是什么?当前s[0..i-1]和p[0..j-1]匹配成功。并且我们不需要管这当中是如何匹配的,这就是动态规划中的无后效性。所以可以用动态规划解决这题。

设bool f[i][j]表示s[0..i-1]和p[0..j-1]是否匹配成功。则分有无*两种情况讨论。

当p[j-1]!='*'时
f[i][j] = f[i-1][j-1]              p[j-1]和s[i-1]匹配,消耗s和p的一个字符
        = false                    Otherwise

当p[j-1]='*'时
f[i][j] = f[i-1][j]||f[i][j-2]     p[j-2]和s[i-1]匹配。消耗s的一个字符,或者也可以选择不匹配p[j-2]和s[i-1],消耗掉p的两个字符
        = f[i][j-2]                否则消耗掉p的两个字符

在进行动态规划之前还应该注意边界条件:

f[0][0]=true                            空串和空串匹配是成功的
f[i][0]=false, i=1..n                   模式串为空时匹配任何非空字符串都失败
f[0][j]=f[0][j-2], j>1且p[j-1]='*'      如果s是空串的话必须*才可以匹配
       =false          否则无法匹配空串

最后返回f[m][n]即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值