[leetcode] 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

 

https://oj.leetcode.com/problems/wildcard-matching/

思路1:二维动归(提交竟然空间超出错误)。 dp[i][j]代表p[0...i]是否匹配 s[0...j]。

  • 如果p[i]!='*',t[i][j] == true 当 t[i-1][j-1]==true &&(p[i]==s[j]||p[i]='.')
  • 如果p[i]=='*',t[i][j]== true 当 其中一个m使得 t[i-1][m]==true,where 0<=m<j.

思路2:二维状态压缩为一维,原理是一样的。

 

思路1和思路2代码:

/**
 * http://www.darrensunny.me/leetcode-wildcard-matching-2/
 * http://www.wangqifox.cn/wordpress/?p=396
 * 
 * @author Dong Jiang
 * 
 */

public class Solution {

    // MLE, the states can be compressed.
    public boolean isMatchOld(String s, String p) {
        if (s == null)
            return p == null;
        if (p == null)
            return s == null;

        int m = p.length();
        int n = s.length();

        boolean[][] dp = new boolean[m + 1][n + 1];
        dp[0][0] = true;
        for (int i = 1; i <= m; i++) {
            if (p.charAt(i - 1) == '*') {
                int j = n + 1;
                for (int k = 0; k <= n; k++) {
                    if (dp[i - 1][k])
                        j = k;
                }
                for (; j <= n; j++)
                    dp[i][j] = true;

            } else {
                for (int j = 1; j <= n; j++) {
                    if (dp[i - 1][j - 1] && (p.charAt(i - 1) == s.charAt(j - 1) || p.charAt(i - 1) == '?'))
                        dp[i][j] = true;
                }
            }
            dp[i][0] = dp[i - 1][0] && (p.charAt(i - 1) == '*');
        }

        return dp[m][n];
    }

    public boolean isMatch(String s, String p) {
        if (s == null)
            return p == null;
        if (p == null)
            return s == null;

        int m = p.length();
        int n = s.length();

        int count = 0;
        for (int i = 0; i < m; i++) {
            if (p.charAt(i) != '*')
                count++;
        }
        if (count > n)
            return false;

        boolean[] dp = new boolean[n + 1];
        dp[0] = true;
        for (int i = 1; i <= m; i++) {
            if (p.charAt(i - 1) == '*') {
                int j = n+1;
                for (int k = 0; k <= n; k++) {
                    if (dp[k]){
                        j = k;
                        break;
                    }
                }
                for (; j <= n; j++)
                    dp[j] = true;

            } else {
                for (int j = n; j >= 1; j--) {
                    dp[j]= (dp[j - 1] && (p.charAt(i - 1) == s.charAt(j - 1) || p.charAt(i - 1) == '?'));
                }
            }
            dp[0] = dp[0] && (p.charAt(i - 1) == '*');
        }

        return dp[n];
    }

    public static void main(String[] args) {
        System.out.println(new Solution().isMatch("ab", "*a"));
    }
}

 

第二遍记录:注意有一行,因为一维是与上一次循环公用数组(意味着默认不一定是false了),所以不仅要赋值true的情况,还要赋值false的情况。

public class Solution {
    public boolean isMatch(String s, String p) {
        if (s == null)
            return p == null;
        if (p == null)
            return s == null;

        int m = p.length();
        int n = s.length();

        // to deal with the hardest case...
        int count = 0;
        for (int i = 0; i < m; i++) {
            if (p.charAt(i) != '*')
                count++;
        }
        if (count > n)
            return false;

        boolean[] dp = new boolean[n + 1];
        dp[0] = true;
        for (int i = 1; i <= m; i++) {
            if (p.charAt(i - 1) == '*') {
                int j = n + 1;
                for (int k = 0; k <= n; k++) {
                    if (dp[k]) {
                        j = k;
                        break;
                    }
                }
                for (; j <= n; j++)
                    dp[j] = true;

            } else {
                for (int j = n; j >= 1; j--) {
                    //be careful of this line
                    dp[j]= (dp[j - 1] && (p.charAt(i - 1) == s.charAt(j - 1) || p.charAt(i - 1) == '?'));
                }

            }
            dp[0] = dp[0] && (p.charAt(i - 1) == '*');
        }

        return dp[n];

    }
}

 

 

参考:

http://www.darrensunny.me/leetcode-wildcard-matching-2/

http://www.wangqifox.cn/wordpress/?p=396

 

 

posted @ 2014-06-26 19:58  jdflyfly  阅读(343)  评论(4编辑  收藏  举报