[leetcode] 44. 通配符匹配(Java)(动态规划)

44. 通配符匹配

动态规划

做动态规划很简单,三步走:

第一步,判断可否用动态规划做,即判断是否满足两个条件:①最优子结构,②重叠子问题。显然该题求s与p是否match,可由其字串层层分解上来。
我语文不好一两句解释不清楚,不过看完这篇文章,基本就会判断是不是满足这两个条件了。
算法-动态规划 Dynamic Programming--从菜鸟到老鸟

第二步,描述状态。这个题的状态还是比较好描述的,boolean f[i][j] :表示子串s[0~i-1] 与子串p[0~j-1]是否match

第三步,找出状态转移方程以及初始状态:

最难的地方就在于如何找状态转移方程。
如何找?即分析当前状态由上层哪个或者哪些以及处理过的状态转换而来
假设题中没有*,那就简单了,状态转移方程为f[i][j] = f[i-1][j-1] && s[i]==p[j]

现在加上,我们就可以按情况讨论嘛,如果p[j]!='' ,那么状态转移方程就是f[i][j] = f[i-1][j-1] && s[i]==p[j]
如果p[j]=='' , 即可以代替0个、1个或者多个,对于的状态f[i][j]可以由f[i-1][j-1],f[i][j-1]和f[i-1][j]而来,即f[i][j] = f[i - 1][j - 1] || f[i - 1][j] || f[i][j - 1];

初始状态,显然f[0][0]=true
不过,还有一个初始状态很容易被遗忘:
当p以开头时
if (p.length() > 0 && p.charAt(0) == '
') {
f[0][1] = true;
}

代码

class Solution {
    public boolean isMatch(String s, String p) {
        String tp = "";

        //处理p中多余的*
        for (int i = 0; i < p.length(); i++) {
            if (p.charAt(i) == '*') {
                tp += '*';
                while (i < p.length() && p.charAt(i) == '*') i++;
            }
            if (i < p.length()) {
                tp += p.charAt(i);
            }
        }
        p = tp;

        boolean[][] f = new boolean[s.length() + 1][p.length() + 1];
        f[0][0] = true;

        // 注意,当p以*开头时
        if (p.length() > 0 && p.charAt(0) == '*') {
            f[0][1] = true;
        }

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

        return f[s.length()][p.length()];
    }
}
posted @ 2018-07-21 13:32 ACBingo 阅读(...) 评论(...) 编辑 收藏