zoukankan      html  css  js  c++  java
  • lintcode192


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

    DP。 O(m*n), m为string长度,n为pattern长度
    1.定义:dp[i][j]是s.substring(0, i)和p.substring(0, j)是否为匹配对,从头开始对比。
    2.状态转移方程:
    a)dp[i][j] = dp[i - 1][j - 1]; 在两个字符相等或p的字符为’?’时。(从左上来)
    b)dp[i][j] = dp[i - 1][j] || dp[i][j - 1]; 在p的字符为’*’时。(从上来和从左来)
    c)dp[i][j] = false; 其他情况,其实也就是两个字符不相同而且p的不是特殊字符时。
    3.初始化:dp[0][0]=true, 第一行也就是声明空s是否匹配一段段pattern的时候,如果遇到p.c ==‘*’的情况,要取左边的值(为了保证比如aa能匹配上*)。第一列也就是声明空p是否匹配一段段的string,肯定都是false啊。
    4.刷新方向,自上而下,从左到右。
    5.具体解释:
    2a)在字符串相等或者’?’被迫匹配到s的当前字符的时候,当前位置合格了,你得把这两个字符擦掉看前面的合格不合格。
    2b)dp[i - 1][j]就是把s擦掉一个而p的*保留,也就是p发挥了万能符的通常作用代表了s里的其中一个字符,至于有没有进一步代表s里其他字符那是dp[i-1][j]帮你去判断的事。
    dp[i][j - 1]就是把s保留而p的*擦掉一个,也就是p发挥了万能符的隐身作用,替代0个字符。
    2c)普通字符当前位置都匹配不上那就不可能了,你整个字符串宏观看,最后一个是普通字符而且不一样的话,前面的*?再怎么巧妙也解决不了最后不同的问题啊。

    细节:
    1.数组大小是[s.length()+1][p.length()+1],留出上左的行列给初始化的。所以给数组赋值的下标和取substring的下标有一个offset,要小心。所以正式part循环是[1, length()],取char是substring(i - 1)。

    参考视频:https://www.youtube.com/watch?v=3ZDZ-N0EPV0

    我的实现

    public class Solution {
        /**
         * @param s: A string 
         * @param p: A string includes "?" and "*"
         * @return: is Match?
         */
        public boolean isMatch(String s, String p) {
            // write your code here
            
            boolean[][] isMatch = new boolean[s.length() + 1][p.length() + 1];
            isMatch[0][0] = true;
            
            for (int j = 1; j <= p.length(); j++) {
                // 注意数组的下标和读取string里的下标有一个offset!
                if (p.charAt(j - 1) == '*') {
                    isMatch[0][j] = isMatch[0][j - 1];
                }
            }
            
            for (int i = 1; i <= s.length(); i++) {
                for (int j = 1; j <= p.length(); j++) {
                    if (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '?') {
                        isMatch[i][j] = isMatch[i - 1][j - 1];
                    } else if (p.charAt(j - 1) == '*') {
                        isMatch[i][j] = isMatch[i - 1][j] || isMatch[i][j - 1];
                    }
                }
            }
            
            return isMatch[s.length()][p.length()];
        }
    }
  • 相关阅读:
    floating IP 原理分析
    创建 floating IP
    Why Namespace?
    虚拟 ​router 原理分析- 每天5分钟玩转 OpenStack(101)
    链接脚本使用一例2---将二进制文件 如图片、MP3音乐、词典一类的东西作为目标文件中的一个段
    linux-2.6.26内核中ARM中断实现详解(转)
    有关Cache –(1) linux list之中的Prefetc
    Linux 内核中的 GCC 特性
    对entry-common.S和call.S的部分理解1
    kernel&uboot学习笔记
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/9577285.html
Copyright © 2011-2022 走看看