LeetCode: Wildcard Matching 解题报告

Wildcard Matching
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

SOLUTION 1:

DP.

动态规划:输入两个字符串s,p(p包含通配符,用p去匹配s),用flag[i][j]表示字符串p从0到i的的子字符串能否匹配s从0到j的子字符串,我们可以得到如下递推公式:

如果p.charAt(i)==s.charAt(j)或则p.charAt(i)==‘?‘,相当于将最后一个字符匹配掉,所以

flag[i][j]=flag[i-1][j-1];

如果p.charAt(i)==‘*‘,‘*‘可以选择匹配0个字符,此时flag[i][j]=flag[i-1][j];可以选择匹配1个字符,此时flag[i][j]=flag[i-1][j-1];……所以,

flag[i][j]=flag[i-1][j]||flag[i-1][j-1]||……||flag[i-1][0]。

但是上面的公式可以化简,当p.charAt(i)==‘*‘时,有

flag[i][j-1]=flag[i-1][j-1]||flag[i-1][j-2]||……||flag[i-1][0]

所以

flag[i][j]==flag[i-1][j]||flag[i][j-1],所以综合递推公式如下:

空间复杂度?

由上面的公式可以看出,flag[i][j]只与第i行和第i-1行相关,所以只需要开辟两个一维数组即可。空间复杂度是O(n),时间复杂度是O(mn)。

 1 public boolean isMatch1(String s, String p) {
 2         if (s == null || p == null) {
 3             return false;
 4         }
 5
 6         int lens = s.length();
 7         int lenp = p.length();
 8
 9         // 创建一个Dp二维数组
10         boolean[][] D = new boolean[lens + 1][lenp + 1];
11
12         boolean flag = false;
13
14         for (int i = 0; i <= lens; i++) {
15             flag = false;
16             for (int j = 0; j <= lenp; j++) {
17                 // both is empty.
18                 if (i == 0 && j == 0) {
19                     D[i][j] = true;
20                     flag = true;
21                     continue;
22                 }
23
24                 // if P is empty, s is not empty, it is false.
25                 if (j == 0) {
26                     D[i][j] = false;
27                     continue;
28                 }
29
30                 // if S is empty, P is not empty
31                 if (i == 0) {
32                     D[i][j] = D[i][j - 1] && p.charAt(j - 1) == ‘*‘;
33                 } else {
34                     D[i][j] = (matchChar(s.charAt(i - 1), p.charAt(j - 1)) && D[i - 1][j - 1])
35                       || (p.charAt(j - 1) == ‘*‘ && (D[i][j - 1] || D[i - 1][j]));
36                 }
37
38                 if (D[i][j]) {
39                     flag = true;
40                 }
41
42                 // Greedy. 在此即可以退出,因为* 可以匹配余下的所有的字符串。
43                 if (D[i][j] && p.charAt(j - 1) == ‘*‘ && j == lenp) {
44                     return true;
45                 }
46             }
47
48             if (!flag) {
49                 return false;
50             }
51         }
52
53         return D[lens][lenp];
54     }
55
56     public static boolean matchChar(char c, char p) {
57         return (p == ‘?‘ || p == c);
58     }
59 }

但是这个算法过不了Leetcode的大数据检查,即使加了几个优化也是如此。

SOLUTION 2:

下面是迭代程序,要熟悉这个思维:记录上一次开始比较的位置,如图:

下面程序是直接使用指针记录位置(JAVA中就使用一个index就好了)

 1     public static boolean matchChar(char c, char p) {
 2         return (p == ‘?‘ || p == c);
 3     }
 4
 5     public static boolean isMatch(String s, String p) {
 6         if (s == null || p == null) {
 7             return false;
 8         }
 9
10         int indexS = 0;
11         int indexP = 0;
12
13         int lenS = s.length();
14         int lenP = p.length();
15
16         int preS = 0;
17         int preP = 0;
18
19         boolean back = false;
20
21         while (indexS < lenS) {
22             if (indexP < lenP && matchChar(s.charAt(indexS), p.charAt(indexP))) {
23                 indexS++;
24                 indexP++;
25             } else if (indexP < lenP && p.charAt(indexP) == ‘*‘) {
26                 while (indexP < lenP && p.charAt(indexP) == ‘*‘) {
27                     indexP++;
28                 }
29
30                 //P的最后一个是 *,表示可以匹配任何字符串
31                 if (indexP == lenP) {
32                     return true;
33                 }
34
35                 // 记录下这个匹配位置。
36                 back = true;
37                 preS = indexS;
38                 preP = indexP;
39             } else if (back) {
40                 indexS = ++preS;
41                 indexP = preP;
42             } else {
43                 return false;
44             }
45         }
46
47         // 跳过末尾的所有的*.
48         while (indexP < lenP && p.charAt(indexP) == ‘*‘) {
49             indexP++;
50         }
51
52         if (indexS == lenS && indexP == lenP) {
53             return true;
54         }
55
56         return false;
57     }

请移步至主页君GITHUB:

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/dp/IsMatch.java

九章算法官方解:

http://www.ninechapter.com/solutions/

REF:

http://m4tiku.duapp.com/report?pid=123

http://blog.csdn.net/kenden23/article/details/17123497

时间: 2024-10-22 10:54:59

LeetCode: Wildcard Matching 解题报告的相关文章

LeetCode: Wildcard Matching [043]

[题目] 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 funct

[LeetCode]wildcard matching通配符实现之贪心法

前天用递归LTE,昨天用动态规划LTE,今天接着搞,改用贪心法.题目再放一次: '?'匹配任意字符,'*'匹配任意长度字符串 Some examples: isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "*"

[LeetCode]wildcard matching通配符实现之动态规划

前天wildcard matching没AC,今天接着搞,改用动态规划.题目再放一次: '?'匹配任意字符,'*'匹配任意长度字符串 Some examples: isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "*&q

[LeetCode]wildcard matching通配符实现TLE

leetcode这道题还挺有意思的,实现通配符,'?'匹配任意字符,'*'匹配任意长度字符串,晚上尝试了一下,题目如下: Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. '*' Matches any sequence of characters (including the empty sequence). The matching shoul

LeetCode: Combination Sum 解题报告

Combination Sum Combination Sum Total Accepted: 25850 Total Submissions: 96391 My Submissions Question Solution Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. The

[LeetCode]LRU Cache, 解题报告

题目 Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.

Leetcode: Wildcard Matching. java

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 p

【LeetCode】Subsets 解题报告

[题目] Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example, If S = [1,2,3], a solution is: [ [3], [1], [2], [1,2,

(待解决)LeetCode 10. Regular Expression Matching 解题报告

10. Regular Expression Matching 提交网址: https://leetcode.com/problems/regular-expression-matching/ Total Accepted: 79548 Total Submissions: 361279 Difficulty: Hard Implement regular expression matching with support for '.' and '*'. '.' Matches any sing