zoukankan      html  css  js  c++  java
  • Leetcode#10 Regular Expression Matching

    原题地址

    这道题坑了我很久,有一组测试数据在本地跑结果是true,但是在Leetcode服务器上跑结果就是false,让我百思不得其解。后来费了好久才终于找到原因,原来还是自己的代码不够严谨,为了让代码简洁一些,有一个判断语句默认空闲内存都是0,结果就错了。

    这道题没有什么技巧,匹配的思路很直观,如果当前字符是*,直接跳过;如果不是*,该怎么处理要看下一个字符是不是*

    1. 如果下一个字符不是*,那么这个字符必须能够被匹配,然后继续
    2. 如果下一个字符是*,那么这个字符要匹配0,1,2,3...次,一直尝试下去

    代码:

     1 bool matchp(const char *s, const char *p) {
     2   if (!*s) {
     3     while (*p && (*p == '*' || *(p + 1) == '*'))
     4       p++;
     5     return !*p;
     6   }
     7   else if (!*p)
     8     return false;
     9 
    10   if (*p == '*')
    11     return matchp(s, p + 1);
    12 
    13   if (*(p + 1) != '*')
    14     return (*p == '.' || *s == *p) && matchp(s + 1, p + 1);
    15   else {
    16     do {
    17       if (matchp(s, p + 2))
    18         return true;
    19       s++;
    20     } while (*(s - 1) && (*p == '.' || *(s - 1) == *p));
    21     return false;
    22   }
    23 }
    24 
    25 bool isMatch(const char *s, const char *p) {
    26   if (!*p)
    27     return !*s;
    28 
    29   return matchp(s, p);
    30 }

    虽然上面的代码已经可以AC了,但是耗时33ms,因为对于特定的匹配串效率很低,比如某个串包含好多a*b*c*...之类的,但最终结果是不能匹配,这个时候算法就会浪费大量时间递归回溯,可以小优化一下。

    我的做法是先对正则串进行化简,然后再匹配。化简规则如下:

    1. 相邻的多个*只保留一个
    2. 对于X*Y*这种形式,如果X和Y都不是"."且X和Y相同,则只保留一个。例如,a*a*简化为a*
    3. 对于X*Y*这种形式,如果X和Y任意一个为".",则只保留"."。例如:a*.*或.*a*都可以简化成.*

    比如一个匹配串是.*bc*.*b*b*a*.bc*,经过简化之后变成了.*b.*.bc*,效果还是很明显的。

    优化后的代码:

     1 bool matchp(const char *s, const char *p) {
     2   if (!*s) {
     3     while (*p == '*' || *(p + 1) == '*')
     4       p++;
     5     return !*p;
     6   }
     7   else if (!*p)
     8     return false;
     9 
    10   if (*p == '*')
    11     return matchp(s, p + 1);
    12 
    13   if (*(p + 1) != '*')
    14     return (*p == '.' || *s == *p) && matchp(s + 1, p + 1);
    15   else {
    16     do {
    17       if (matchp(s, p + 2))
    18         return true;
    19       s++;
    20     } while (*(s - 1) && (*p == '.' || *(s - 1) == *p));
    21     return false;
    22   }
    23 }
    24 
    25 const char *simplify(const char *p) {
    26   string reg;
    27   char prev;
    28 
    29   reg.push_back(*p);
    30   prev = *p;
    31   for (p++; *p; p++) {
    32     if (reg.back() == '*') {
    33       if (*p == '*')
    34         continue;
    35       if (*(p + 1) == '*') {
    36         if (*p == '.') {
    37           while (reg.back() == '*') {
    38             reg.pop_back();
    39             reg.pop_back();
    40           }
    41           prev = *p;
    42           reg.push_back(*p);
    43         }
    44         else if (prev != '.' && *p != prev) {
    45           prev = *p;
    46           reg.push_back(*p);
    47         }
    48       }
    49       else {
    50         prev = *p;
    51         reg.push_back(*p);
    52       }
    53     }
    54     else {
    55       reg.push_back(*p);
    56       if (*p != '*')
    57         prev = *p;
    58     }
    59   }
    60 
    61   char *res = new char[reg.length()];
    62   strcpy(res, reg.c_str());
    63 
    64   return res;
    65 }
    66 
    67 bool isMatch(const char *s, const char *p) {
    68   if (!*p)
    69     return !*s;
    70 
    71   simplify(p); // new
    72 
    73   return matchp(s, p);
    74 }

     

    优化后耗时9ms

  • 相关阅读:
    Apollo 配置中心
    Sentinel 限流
    soul 网关
    xxl-job 任务管理
    java Young GC排查
    bitmap(位图)
    RabbitMQ一个简单可靠的方案(.Net Core实现)
    从技术角度讨论微服务
    你可能不知道的.Net Core Configuration
    浅谈开发模式及架构发展
  • 原文地址:https://www.cnblogs.com/boring09/p/4235616.html
Copyright © 2011-2022 走看看