zoukankan      html  css  js  c++  java
  • leetcode Wildcard Matching greedy algrithm

    The recursive program will result in TLE like this:

    class Solution {
     public:
      bool isMatch(const char *s, const char *p) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
        if (*s == *p && *s == '')
          return true;
        if (*p == '?' || *s == *p)
          return isMatch(s + 1, p + 1);
        else if (*p == '*') {
          int i;
          for (i = 0; *(s + i); ++i)
            if (isMatch(s + i, p + 1))
              return true;
          if (isMatch(s + i, p + 1))
            return true;
          
          return false;
        }
        else if (*p != *s)
          return false;
      }
    };


    So it's necessary to write an non-recursive program. The key point is to match the '*' in p string. We could attempt to match '*' with 0...n characters in s, i.e., the character after '*' maybe match any position in s regardless a series of characters in s. Take notice that consecutive '*'s are equal to one '*'. Based on that, a lengthy code is written as :

    class Solution {
     public:
      bool isMatch(const char *s, const char *p) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
        bool star = false, staremerge = false;
        const char *str = s, *ptr = p, *ss = s, *pp = p;
        for (str = ss, ptr = pp; *str && *ptr || *str == '' && *ptr == '*'; ++str, ++ptr) {
          if (*ptr == '*') {
            star = staremerge = true;
            while (*ptr == '*')
              ++ptr;
            if (*ptr == '')
              return true;
            ss = str;
            pp = ptr;
            --str;
            --ptr;
          }  
          else {
            if (!star) {
              if( !staremerge ) {
                if (*str != *ptr && *ptr != '?' ||*(ptr + 1) == '' && *(str + 1) != '')  
                  return false;
              }
              else {
                if (*str != *ptr && *ptr != '?' ||*(ptr + 1) == '' && *(str + 1) != '') {
                  str = ss++;
                  ptr = pp - 1;
                  star = true;
                }
                  
              }
            }
            else if (star) {
              if ( *str != *ptr && *ptr != '?') {
                ss = str + 1;  
                --ptr;
              }
              else {
                star = false;
                if (*(ptr + 1) == '' && *(str + 1) != '') {
                  str = ss++;
                  ptr = pp - 1;
                  star = true;
                }            
              }
            }
          }
        }
        if (*str == *ptr && *str == '')
          return true;
        else
          return false;
      }
    };


    Some suggestions about this code: 

    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 {
     public:
      bool isMatch(const char *s, const char *p) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
        const char *sbegin = s, *pbegin = p, *str = s, *ptr = p;
        bool star = false;
        for (str = s, ptr = p; *str || *ptr == '*'; ++str, ++ptr) {
          if (*ptr == '*') {
            star = true;
            while (*ptr == '*') 
              ++ptr;
            if (*ptr == '')
              return true;
            pbegin = ptr--;
            sbegin = str--;
          }
          else if (*str != *ptr && *ptr != '?'){
            if (!star)
              return false;
            str = sbegin++;
            ptr = pbegin - 1;
          }
        }
        return *ptr == '';  
      }
    };



  • 相关阅读:
    cf1058c 暴力
    cf1058b 点是否在一个矩形里
    cf1058E 思维 前缀处理 位运算
    Codeforces Round #622 (Div. 2)C(单调栈,DP)
    Codeforces Round #623 (Div. 1, based on VK Cup 2019-2020
    Atcoder Beginner Contest 156E(隔板法,组合数学)
    【PAT甲级】1117 Eddington Number (25分)
    【PAT甲级】1116 Come on! Let's C (20分)
    【PAT甲级】1115 Counting Nodes in a BST (30分)(二叉查找树)
    Codeforces Round #621 (Div. 1 + Div. 2)E(二分查找,枚举分界点,容斥原理)
  • 原文地址:https://www.cnblogs.com/james1207/p/3395436.html
Copyright © 2011-2022 走看看