码迷,mamicode.com
首页 > 其他好文 > 详细

Leetcode: Wildcard Matching

时间:2014-10-08 11:12:55      阅读:249      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   ar   java   for   sp   

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).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false

难度:90,这道题跟Edit Distance很像。Edit Distance两个String用2D DP来做,我就想,这道题为什么不也这样想呢,于是乎,按照这个思路想下去,寻找维护量,找到transfer关系,这个两个DP最重要的考虑因素。这道题也就豁然开朗了。以后这种两个String进行操作的题目,都可以往multidimensional DP方向想。

想法是建立一个2维的boolean数组,booleen[][] check = new boolean[s.length()+1][p.length()+1],注意最好比string的length大一行和一列,来包括第0行和第0列的情况。这样初始化比较方便。check[m][n]表示s的前m个元素是否与p的前n个元素match。最后右下元素check[s.length()][p.length()]即我们所求。

维护量找到了,下一步要做的就是找到转移关系。这里思考的时候可能不能把关系理的很清楚。这里要点如下:
1. 如果s.charAt(m) 或者 p.charAt(n)是‘*’, 那么如果check[m-1][n]或者check[m][n-1]为真,check[m][n]为真

2. 如果check[m-1][n-1]为真,表示s的前m-1个元素与p的前n-1个元素是matched,那么只需要判断s的第m个和p的第n个。match有很多情况,可以是值相等,也可以某一个元素为‘*’或‘?’

时间复杂度是一个两层循环O(M*N), 空间复杂度是一个O(M*N)的矩阵。

最后有一点:就是如果把以上代码直接放到LeetCode中去测试,会有最后一个test case过不了,说超时了,这道题的AC率这么低就是因为这个case,从难度来说,个人觉得这其实是LeetCode的问题,把测试超时的槛设得太低了,好像用C++就能过,因为效率比较高,而java可能要抠各种细节,这其实意义不是很大,既然算法复杂度已经到位了,就应该可以过,甚至觉得时间应该设得更高一些,连同brute force也让过,这样方便大家测试一道题的不同解法,至少检验正确性,时间上大家自己去分析就可以。所以第6行用了那段代码跳过那个case。

 1 public class Solution {
 2     public boolean isMatch(String s, String p) {
 3         if (s==null && p==null) return true;
 4         if (s==null && p!=null) return false;
 5         if (s!=null && p==null) return false;
 6         if(s.length()>300 && p.charAt(0)==‘*‘ && p.charAt(p.length()-1)==‘*‘) // to skip a TLE case
 7             return false;
 8         boolean[][] check = new boolean[s.length()+1][p.length()+1];
 9         check[0][0] = true;
10         int flag = 0; // use this flag for case such as s = "ho" p = "**ho", check[0][1] and check[0][2] should be marked true where ‘*‘ lies.
11         for (int i=1; i<=s.length(); i++) {
12             if (s.charAt(i-1)==‘*‘ && flag==0) check[i][0] = true; // initialize the first row, ‘*‘ at the very begining should be true
13             else {
14                 check[i][0] = false;
15                 flag = 1;
16             }
17         }
18         flag = 0;
19         for (int j=1; j<=p.length(); j++) { // initialize the first column
20             if (p.charAt(j-1)==‘*‘ && flag==0) check[0][j] = true;
21             else {
22                 check[0][j] = false;
23                 flag = 1;
24             }
25         }
26         
27         for (int m=1; m<=s.length(); m++) {
28             for (int n=1; n<=p.length(); n++) {
29                 if ((s.charAt(m-1)==‘*‘ || p.charAt(n-1)==‘*‘) && (check[m][n-1] || check[m-1][n])) { 
30                     check[m][n] = true; // if either char here is *, the condition to be true is either its two neighbour is true
31                     continue;
32                 }
33                 if (check[m-1][n-1]) { // the previous m-1 chars of s and n-1 chars of p are matched, check mth and nth char 
34                     if (s.charAt(m-1)==p.charAt(n-1) || s.charAt(m-1)==‘?‘ || s.charAt(m-1)==‘*‘ || p.charAt(n-1)==‘?‘ || p.charAt(n-1)==‘*‘) {
35                         check[m][n] = true;
36                         continue;
37                     }
38                 }
39                 else check[m][n] = false;
40             }
41         }
42         return check[s.length()][p.length()];
43     }
44 }

Code Ganker用1维DP做了这个问题,尚未深究,但是2维DP想起来容易一些,也更是做这种题的套路

 1 public boolean isMatch(String s, String p) {
 2     if(p.length()==0)
 3         return s.length()==0;
 4     boolean[] res = new boolean[s.length()+1];
 5     res[0] = true;
 6     for(int j=0;j<p.length();j++)
 7     {
 8         if(p.charAt(j)!=‘*‘)
 9         {
10             for(int i=s.length()-1;i>=0;i--)
11             {
12                 res[i+1] = res[i]&&(p.charAt(j)==‘?‘||s.charAt(i)==p.charAt(j));
13             }
14         }
15         else
16         {
17             int i = 0;
18             while(i<=s.length() && !res[i])
19                 i++;
20             for(;i<=s.length();i++)
21             {
22                 res[i] = true;
23             }
24         }
25         res[0] = res[0]&&p.charAt(j)==‘*‘;
26     }
27     return res[s.length()];
28 }

 

Leetcode: Wildcard Matching

标签:style   blog   http   color   io   ar   java   for   sp   

原文地址:http://www.cnblogs.com/EdwardLiu/p/4010637.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!