LeetCode刷题笔记-10

LeetCode-10. Regular Expression Matching(Hard):

Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.

'.' Matches any single character.
'*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

Note:

  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like . or *.

Example 1:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

Example 3:

Input:
s = "ab"
p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".

Example 4:

Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".

Example 5:

Input:
s = "mississippi"
p = "mis*is*p*."
Output: false

我的解法:

第一次解得时候就用暴力判断的方法,和第44题不同的是,这道题硬解是能解出来的

class Solution:
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        sLen = len(s)
        pLen = len(p)
        if (pLen == 0):
            return sLen == 0
        if (pLen == 1):
            if (p == s) or ((p == '.') and (len(s) == 1)):
                return True
            else:
                return False
        #p的最后一个字符不是'*'也不是'.'且不出现在s里,p跟s肯定不匹配
        if (p[-1] != '*') and (p[-1] != '.') and (p[-1] not in s):
            return False
        if (p[1] != '*'):
            if (len(s) > 0) and ((p[0]==s[0]) or (p[0]=='.')):
                return self.isMatch(s[1:],p[1:])
            return False
        else:
            while (len(s) > 0) and ((p[0]==s[0]) or (p[0]=='.')):
                if (self.isMatch(s,p[2:])):
                    return True
                s = s[1:]
            return self.isMatch(s,p[2:])

但是因为刚刚学了动态规划,总结到这里就尝试用动态规划解决一下这个问题

首先找一个样例:

s = "mississippi"
p = "mis*is*p*."

列出状态数组dp的值:

s\p0mis*is*p*.
010000000000
m01000000000
i00101000000
s00011000000
s00001000000
i00000101010
s00000011011
s00000001011
i00000000001
p00000000000
p00000000000
i00000000000

列出状态转移方程:

dp(0,0)=0;

if p[j]='*', dp(i,j) = dp(i,j-1) || dp(i,j-2) ||  (  (dp(i-1,j-1) || dp(i-1,j) ) && (s[i] = p[j-1] || p[j-1]='.')  )

if p[j]!='*',dp(i,j) = dp(i-1,j-1) && (s[i]=p[j] || p[j]='.')

当然,状态转移方程可能不是一次列出来就考虑到了所有情况,提交之后出现问题再改(上面是改对之后的)

在写代码的过程中还要注意对dp(0,*)和dp(*,0)的初始化,还要考虑i、j减一和减二时的边界问题,另外,注意s、p字符串的下标和dp二维数组的下标是错一位的,要注意减一。

class Solution {
    public boolean isMatch(String s, String p) {
        int slen = s.length();
        int plen = p.length();
        int[][] dp = new int[slen+1][plen+1];
        //初始化
        dp[0][0] = 1;
        for(int t=1; t<=slen; t++){
            dp[t][0] = 0;
        }
        for(int t=1; t<=plen; t++){
        	if(t==1) {
        		dp[0][t] = 0;
        	}
        	else if(t==2) {
        		if(p.charAt(t-1)=='*') {
        			dp[0][t] = 1;
        		}
        		else {
        			dp[0][t] = 0;
        		}
        	}
        	else if(p.charAt(t-1) == '*' && t>2 && dp[0][t-2] == 1) {
        	    dp[0][t] = 1;           	
            }
        	else {
        		dp[0][t] = 0;
        	}
        }
        //根据状态转移方程求dp的所有值
        for(int i=1; i<=slen; i++) {
        	for(int j=1; j<=plen; j++) {
        		if(p.charAt(j-1) == '*') {
        			if(j>1) {
        				dp[i][j] = dp[i][j-1] | dp[i][j-2] | (dp[i-1][j-1] | dp[i-1][j]) & ((s.charAt(i-1)==p.charAt(j-1-1)?1:0) | (p.charAt(j-1-1)=='.'?1:0));
        			}                    
        			else {
        				dp[i][j] = dp[i][j-1] | (dp[i-1][j-1] & ((s.charAt(i-1)==p.charAt(j-1-1)?1:0) | (p.charAt(j-1-1)=='.'?1:0)));
        			}
        		}
        		else {
        			dp[i][j] = dp[i-1][j-1] & ((s.charAt(i-1)==p.charAt(j-1)?1:0) | (p.charAt(j-1)=='.'?1:0));
        		}
        	}
        }
        if(dp[slen][plen] == 1) {
        	return true;
        }
        else {
        	return false;
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值