• Leetcode 44. Wildcard Matching


    44. Wildcard Matching

    题目链接https://leetcode.com/problems/wildcard-matching/

    Description:

    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 = "adceb"
    p = "*a*b"
    Output: true
    Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".
    

    Example 2:

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

    题意:

    给出两个字符串,一个是匹配串,另一个是用来匹配的串,其中*代表任意的数,包括无数;"?"代表任意的一个字符。

    现在问两个串是否能够成功匹配。

    题解:

    这题dp应该还是好做,dp[i,j]含义为第一个串匹配前i个,第二个串匹配前j个是否能够成功匹配。

    初始化为dp[0,0]=1,然后转移方程为:

    dp[i,j]=dp[i-1,j-1] && s[i-1]==p[j-1] || p[j-1]=="?"  ;  if(p[j-1]=="*") dp[i,j]=dp[i-1,j] || dp[i,j-1] || dp[i-1,j-1]。

    对第二个式子解释一下吧,如果当前的p是"*",那么当前状态可能就由三种情况转移过来:

    1."*"匹配了第i-1个字符,现在继续匹配第i个;2."*"不匹配,即当做空;3."*"作为开头来匹配第i个字符。

    然后就可以做了,代码如下:

    class Solution {
    public:
        bool isMatch(string s, string p) {
            int n = s.length(), m = p.length();
            int dp[n+5][m+5];
            memset(dp,0,sizeof(dp));
            dp[0][0]=1;
            for(int i=1;i<=m;i++){
                if(p[i-1]=='*'){
                    dp[0][i]=1;
                    continue ;
                }
                break ;
            }
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    dp[i][j]=(dp[i-1][j-1]&&(s[i-1]==p[j-1] || p[j-1]=='?'));
                    if(p[j-1]=='*') dp[i][j]=(dp[i-1][j]||dp[i][j-1]||dp[i-1][j-1]);
                }
            }
            return dp[n][m];
        }
    };
    View Code

    但是这里dp的复杂度是O(n^2),复杂度有点高,我们可以换一种思路来解,即指针法。

    这个方法有点巧妙,类似于模拟,即定义两个i,j指针,分别在两个字符串中,现在同样有几种情况:

    假设当前s[i-1]==p[j-1] || p[j-1]=="?",意即能够重新匹配,我们i++,j++;

    还有一种情况就是当前的p[j-1]=="*",那么我们记录下i当前的位置,以及让j++,继续匹配。

    如果出现匹配不成功的情况,那么就让j回到刚才记录的"*"之后那一位,否则无解;让i回到刚才记录i的位置的下一位继续匹配。

    就不断重复这样的匹配操作,如果再一次遇到一个"*",那么我们就更换"*"的位置,采用最近的"*",这是最优的,因为这里的"*"可以看作空,也就是说既可以从之前那里匹配过来,也可以从当前这里开始匹配,这样时间复杂度会小些,不然又O(n^2)了。

    以上就是该算法的大体思想,另外注意一下代码的实现,最后的时候要记得看是否两个指针都到了末尾,这样才算匹配成功。

    注意一下代码的细节,建议亲自实现。

    代码如下:

    class Solution {
    public:
        bool isMatch(string s, string p) {
            int n = s.length(), m = p.length();
            int i=0,j=0;
            int pre=-1,alp=-1;
            while(i<n){
                if(j<m&&(s[i]==p[j]||p[j]=='?')) i++,j++;
                else if(j<m&&p[j]=='*'){
                    pre = j++;
                    alp = i;
                }else if(pre>-1){
                    j = pre+1;
                    i = ++alp;
                }else return false ;
            }
            while(j<m && p[j]=='*') j++;
            return j==m;
        }
    };
    View Code
  • 相关阅读:
    第6天c#基础结构体和数组
    第5天c#基础for循环和enum
    第4天c#基础switch和while循环
    第3天c#按位运算和增减buff
    第2天c#基础
    第1天c#基础语法
    背景图层填充底色调密度
    如何在运行里添加命令
    网站
    BAT设置
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10230128.html
Copyright © 2020-2023  润新知