查看: 7880| 回复: 16
跳转到指定楼层
上一主题 下一主题
收起左侧

[Leetcode]花半年解决Wildcard Matching 而且还是用Python另附完整Java

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
本帖最后由 Linzertorte 于 2014-7-10 19:24 编辑

找工作的时候刷leetcode,主要用C++刷了140题。但是Wildcard matching死活过不了。
类似的regular expression matching用回溯过了。
然后今天受到一个启发用Non-deterministic automata来做。一个bit_vector表示当前状态。
然后这个NFA也很好构造。如果对应位置有个*,说明有一个自环。如果是字母或者?,有一个走向下一状态的边。
代码倒是好写。

首先这题如果有连续有*.那么只保留一个即可。
这个复杂度为O(m*n) m 是len(s), n是len(p)



然后发就Time limited exceed在之前C++就通不过那个长长的"aaaaaaaaaaaaaaaaaaaaaaaaa..."上。然后就以为是因为他有许多"aaaa",然后pattern是一个aaaa*所以过了不。
然后就想到一个优化。把pattern分解成三个部分 第一部分与第三部分都没有*
left,middle, right
比如pattern=abc*daf?*dsaf*?df
left=abc
middle = *daf?*dsaf*
right = ?df



我们定义match_from(i,s,p)  即一个不含*,可能含有?的pattern p可以match s[i..i+len(pattern)-1]
然后还是超时。

不过这个将pattern分成三部分的想法又给了我一个启发。

其实我们完全可以将这个pattern按照*来split.得到的chunks都不含有*

然后这题要求exact match
所以第一个chunk和最后一个chunk必须与s的开头和结尾match



剩下的就是中间的chunks,还有那个去头去尾的s,如果称去头去尾的s为s'

我们接下来的match就可以采取信心的策略。





上面为s',下面就是chunks.
没有arrow指向的s'中字母我们一律用*来match

每个chunk我们只需要尽可能靠左去match.这个不会影响结果。而且这个性质很容易证明。

开始让begin=0
然后发现   match_from(begin,'aaa',s') ==True  
这样aaa match就match上了。
我们让begin += len('aaa')
begin现在是3.
即从3开始match第二个chunk bbc
直到begin==11的时候match_from(begin,'bbc',s')==True
我们又完成了第二个chunk的match..
..如此如此so on and so forth.
然后下面是代码




这一大段主要是用来对s进行掐头去尾。。许多corner case




最后的几行就是小贪心一下。

最后的最后是我的提交记录。真的半年啦






评分

参与人数 5大米 +40 收起 理由
OO0OO + 5 正研究这题
austurela + 5 感谢分享!
ivycheung1208 + 10 赞一记
sanguine + 10
Sun + 10 技术帖!~

查看全部评分


上一篇:leetcode从来没自己做对过
下一篇:大牛战个痛,这道题要是面试几分钟搞定?

本帖被以下淘专辑推荐:

推荐
 楼主| Linzertorte 2014-7-10 19:41:34 | 只看该作者
全局:
回复

使用道具 举报

推荐
ralf 2014-7-10 21:54:15 | 只看该作者
全局:
这题G onsite考到了,我当时写的是:

    bool isMatch(const char *s, const char *p)
    {
        const char* star_pos = 0;
        const char* s_pos = 0;
        
        while(*s != '\0')
        {
           if(*s == *p || *p == '?') //一对一的match
           {
               s++;
               p++;
               continue;
           }
           if(*p == '*') //很多'*'连在一起和一个'*'效果是一样的
           {
               star_pos = p;
               p++;
               s_pos = s;
               continue;
           }
           if(star_pos != 0)
           {
               s = s_pos++; //s_pos的作用是如果s和p在第一个if里不能匹配到底(即p到底s还没到底),s可以重新回到s_pos
                            //s_pos++后重新开始匹配相当于'*'又多消灭s中的一个字符
               p = star_pos+1; //p重新回到star_pos+1
               continue;
           }
           return false; //如果上面三个if都进不去,s又还没到头,那么匹配失败
        }
        while(*p == '*') p++; //忽略剩下的'*'
        return *p == '\0';
    }
回复

使用道具 举报

推荐
 楼主| Linzertorte 2014-7-10 19:22:30 | 只看该作者
全局:
这里附上另外整理的Java代码。

wildcard.jpg (242.71 KB, 下载次数: 13)

wildcard.jpg
回复

使用道具 举报

本楼:
全局:
厉害
回复

使用道具 举报

🔗
pyemma 2014-7-10 20:57:33 | 只看该作者
全局:
当初用java写的,调了一个晚上才过了,一开始用DP超时,后来改用贪心+KMP才过了
回复

使用道具 举报

🔗
 楼主| Linzertorte 2014-7-10 22:10:35 | 只看该作者
全局:
ralf 发表于 2014-7-10 21:54
这题G onsite考到了,我当时写的是:

    bool isMatch(const char *s, const char *p)

幸亏我G onsite没面这题。要不然我就挂了。
回复

使用道具 举报

🔗
 楼主| Linzertorte 2014-7-11 02:38:20 | 只看该作者
全局:
pyemma 发表于 2014-7-10 20:57
当初用java写的,调了一个晚上才过了,一开始用DP超时,后来改用贪心+KMP才过了

KMP点赞。
回复

使用道具 举报

🔗
pyemma 2014-7-11 11:24:08 | 只看该作者
全局:

理解了KMP,写带?的KMP就很简单了
回复

使用道具 举报

🔗
 楼主| Linzertorte 2014-7-11 12:37:59 | 只看该作者
全局:
pyemma 发表于 2014-7-11 11:24
理解了KMP,写带?的KMP就很简单了

这倒也是。计算next指针的时候比如p[i]==?或者p[i]==s[j]都算是匹配成功。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表