LeetCode 44 Wildcard Matching 贪心 DP

本文介绍了一种实现通配符匹配的算法,该算法支持 '?' 和 '*' 两种通配符,其中 '?' 可以匹配任意单个字符,而 '*' 可以匹配任意长度的字符序列。文中提供了贪婪算法及动态规划算法的实现,并通过多个实例验证了算法的有效性。

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

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

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 = "*"
Output: true
Explanation: '*' matches any sequence.

Example 3:

Input:
s = "cb"
p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.

Example 4:

Input:
s = "adceb"
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".

Example 5:

Input:
s = "acdcb"
p = "a*c?b"
Output: false

--------------------------------------------------

Greedy Solution:

1. There is no need to refresh the status of star, staremerge. Only one star is enough, because the character(for example, 'a') always needs to match some 'a' in s. Matching the former 'a' is better than the latter 'a' in s as is illustrated in the figure. I.e., there is no need to record the matching range for every '*', the latest '*' has the largest range of choice. 

2. sbegin is refreshed when mismatch occurs and pbegin is refreshed when meeting new '*';

3. Focusing on s is better than handling the two strings at the same time. 

So the final concise code is like:

class Solution:
    def isMatch(self, s, p):
        slen, plen, i, j = len(s), len(p), 0, 0
        star = False
        while (i < slen):
            if (j < plen and (s[i] == p[j] or p[j] == '?')):
                i += 1
                j += 1
            elif (j < plen and p[j] == '*'):
                star_begin_s = i
                star_begin_p = j+1
                j += 1
                star = True
            elif (star):
                j = star_begin_p
                star_begin_s += 1
                i = star_begin_s
            else:
                return False
        while (j < plen and p[j] == '*'):
            j += 1
        if (j == plen):
            return True
        return False

Using DP, the codes look like:

class Solution {
 public:
  bool isMatch(const char *s, const char *p) {
    int slen = strlen(s), plen = strlen(p), i, j, countp = 0;
    for (const char *ptr = p; *ptr; ++ptr)
      if (*ptr != '*')
        ++countp;
    if (countp > slen)
      return false;
    bool dp[500][500];
    memset(dp,false,sizeof(dp));
    dp[0][0] = true;
    for (i = 1; i <= plen; ++i) {
      dp[i][0] = dp[i - 1][0] && *(p + i -1) == '*';
      for (j = 1; j <= slen; ++j) {
        if (*(p + i -1) == '*')
          dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
        else
          dp[i][j] = dp[i - 1][j - 1] && (*(p + i -1) == *(s + j -1) || *(p + i -1) == '?');
      }
    }
    return dp[plen][slen];
  }
};

DP Solution:

f[i][j] indicates whether p[0..i] matches s[0..j]. So 

if p[i] == '*', dp[i][j] = dp[i][j-1] || dp[i-1][j]

if p[i] != '*', dp[i][j] = dp[i-1][j-1] && single match

reduce two-dimension dp to 1 dimension

class Solution:
    def isMatch(self, s, p):
        slen, plen = len(s), len(p)
        if (plen <= 0):
            return slen == 0
        if (slen <= 0):
            return all(pi == '*' for pi in p)

        f = [p[0] == '*' for i in range(slen)]
        f[0] = (p[0] == '*' or p[0] == s[0] or p[0] == '?')

        match_empty = [False for i in range(plen)] #以i结尾的p是否和s的空前缀匹配
        match_empty[0] = p[0] == '*'
        for i in range(1, plen):
            match_empty[i] = (match_empty[i-1] and p[i] == '*')
        #print(f)
        for i in range(1, plen):
            pre = list(f)
            for j in range(0, slen):
                if (p[i] == '*'):
                    #f[i][j] = f[i][j-1] || f[i-1][j]
                    tmp2 = f[j-1] if j >= 1 else match_empty[i-1]
                    f[j] = f[j] or tmp2
                else:
                    #f[i][j] = f[i-1][j-1]
                    match = (p[i] == s[j]) or (p[i] == '?')
                    tmp = pre[j-1] if j >= 1 else match_empty[i-1]
                    f[j] = tmp and match
            #print(f)

        return f[-1]
s = Solution()
print(s.isMatch("aa","a"))
print(s.isMatch("aa","aa"))
print(s.isMatch("aaa","a"))
print(s.isMatch("aa","*"))
print(s.isMatch("aa","a*"))
print(s.isMatch("ab","?*"))
print(s.isMatch("aab","c*a*b"))
print(s.isMatch("adceb","*a*b"))
print(s.isMatch("a","a*"))

 

这个是完整源码 python实现 Flask,Vue 【python毕业设计】基于Python的Flask+Vue物业管理系统 源码+论文+sql脚本 完整版 数据库是mysql 本文首先实现了基于Python的Flask+Vue物业管理系统技术的发展随后依照传统的软件开发流程,最先为系统挑选适用的言语和软件开发平台,依据需求分析开展控制模块制做和数据库查询构造设计,随后依据系统整体功能模块的设计,制作系统的功能模块图、E-R图。随后,设计框架,依据设计的框架撰写编码,完成系统的每个功能模块。最终,对基本系统开展了检测,包含软件性能测试、单元测试和性能指标。测试结果表明,该系统能够实现所需的功能,运行状况尚可并无明显缺点。本文首先实现了基于Python的Flask+Vue物业管理系统技术的发展随后依照传统的软件开发流程,最先为系统挑选适用的言语和软件开发平台,依据需求分析开展控制模块制做和数据库查询构造设计,随后依据系统整体功能模块的设计,制作系统的功能模块图、E-R图。随后,设计框架,依据设计的框架撰写编码,完成系统的每个功能模块。最终,对基本系统开展了检测,包含软件性能测试、单元测试和性能指标。测试结果表明,该系统能够实现所需的功能,运行状况尚可并无明显缺点。本文首先实现了基于Python的Flask+Vue物业管理系统技术的发展随后依照传统的软件开发流程,最先为系统挑选适用的言语和软件开发平台,依据需求分析开展控制模块制做和数据库查询构造设计,随后依据系统整体功能模块的设计,制作系统的功能模块图、E-R图。随后,设计框架,依据设计的框架撰写编码,完成系统的每个功能模块。最终,对基本系统开展了检测,包含软件性能测试、单元测试和性能指标。测试结果表明,该系统能够实现所需的功能,运行状况尚可并无明显缺点。本文首先实现了基于Python的Flask+Vue物业管理系统技术的发
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值