Wildcard Matching[leetcode]直接匹配和DP

这题类似 Regular Expression Matching,但是数据比较强。

首先介绍DP的解法,回忆Regular Expression Matching,我们也用dp(i,j)表示s[0...i-1]和p[0...j-1]是否匹配

基本情况相似,但是更简单:

1. dp(0,0) = true

2. dp(0,j) = dp(0,j-1) && p[j-1] == ‘*‘

3. dp(i,0) = false

一般情况dp(i,j):

1. dp(i-1,j-1) && (s[i-1] == p[j-1] || p[j-1] == ‘?‘)

2. dp(i, j-1) && p[j-1] == ‘*‘

3. dp(i-1, j) && p[j-1] == ‘*‘

由于第i行只用到了第i-1行的数据,所以可以将空间上压缩至一维。我们用一个bool curRow表示当前访问的行号,!curRow表示i-1行

第一个版本

bool isMatch(const char *s, const char *p) {
        int m = strlen(s);
        int n = strlen(p);
        bool curR = 0;
        vector<vector<bool>> dp(2);
        dp[curR] = (vector<bool>(n+1));
        dp[!curR] = (vector<bool>(n+1));
        dp[0][0] = true;
        for (int i = 1; i <= n; i++)
            dp[0][i] = (p[i-1] == '*' && dp[0][i-1]);

        const char* tmp = p;
        int cnt = 0;
        while (*tmp != '\0') if (*(tmp++) != '*') cnt++;
        if (cnt > m) return false;  

        for (int i = 1; i <= m; i++)
        {
            curR = !curR;
            dp[curR][0]=false;
            for (int j = 1; j <= n; j++)
            {
                dp[curR][j] = (dp[!curR][j-1] && (s[i-1] == p[j-1] || p[j-1] == '?') ||
                            dp[curR][j-1] && p[j-1] == '*' ||
                            dp[!curR][j] && p[j-1] == '*');
            }
        }
        return dp[curR][n];
    }

注意这里有一个剪枝,if (cnt > m) return false,用于迅速将不符合的情况排除。如果没有这一段的话会TLE。

第二个版本

bool isMatch(const char *s, const char *p) {
        int m = strlen(s);
        int n = strlen(p);
        if (!quickElimination(s,p)) return false;
        bool curR = 0;
        vector<vector<bool>> dp(2);
        dp[curR] = (vector<bool>(n+1));
        dp[!curR] = (vector<bool>(n+1));
        dp[0][0] = true;
        for (int i = 1; i <= n; i++)
            dp[0][i] = (p[i-1] == '*' && dp[0][i-1]);

        for (int i = 1; i <= m; i++)
        {
            curR = !curR;
            dp[curR][0]=false;
            for (int j = 1; j <= n; j++)
            {
                if (p[j-1] == '*')
                    dp[curR][j] = dp[curR][j-1] || dp[!curR][j];
                else if (s[i-1] == p[j-1] || p[j-1] == '?')
                    dp[curR][j] = dp[!curR][j-1];
                else
                    dp[curR][j] = false;
            }
        }
        return dp[curR][n];
    }

    bool quickElimination(const char *s, const char *p)
    {
        int cnt = 0;
        while (*p != '\0') if (*(p++) != '*') cnt++;
        if (cnt > strlen(s)) return false;
        return true;
    }

主要的不同是在计算dp(i,j)时用if-else取代一系列的逻辑运算符,速度上提高30%左右。因为第一个版本在计算时,某个语句失败后会计算以||相连的下一个条件,造成更多运算。

复杂度为O(slen*plen)

直接匹配的方法

http://yucoding.blogspot.com/2013/02/leetcode-question-123-wildcard-matching.html上有个非常简单优美的方法,比我第一次几十行的代码优秀太多。

    bool isMatch(const char *s, const char *p) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
         
        const char* star=NULL;
        const char* ss=s;
        while (*s){
            if ((*p=='?')||(*p==*s)){s++;p++;continue;}
            if (*p=='*'){star=p++; ss=s;continue;}
            if (star){ p = star+1; s=++ss;continue;}
            return false;
        }
        while (*p=='*'){p++;}
        return !*p;
    }

主要的思想是:

1.*s==*p or *p == ? :匹配,s++ p++。

2. p==‘*‘:也是一个匹配,但可能有0个或者多个字符用于匹配,所以将‘*‘所在位置保存(star),并且将s的位置也保存下来(ss)。

3. 如果不匹配,查看之前是否有‘*‘。没有则返回false,有则对ss的下一个位置和start之后的重新匹配。

暴力法,复杂度是O(slen*slen)。

由于例子中plen和slen相差不大,而且暴力法在搜索途中就能发现不匹配的字符串,终止搜索;而DP需要在遍历完所有子问题后才能给出解,所以第二种方法快得多。

OJ上,暴力法耗时116ms,DP耗时720ms

时间: 2024-08-14 08:03:42

Wildcard Matching[leetcode]直接匹配和DP的相关文章

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

[LeetCode] Wildcard Matching 字符串匹配,kmp,回溯,dp

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

Wildcard Matching -- leetcode

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 44.Wildcard Matching (通配符匹配) 解题思路和方法

Wildcard Matching '?' 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,

[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】Wildcard Matching 串匹配 动态规划

题目:Wildcard Matching <span style="font-size:18px;">/*LeetCode WildCard matching * 题目:给定一个目标串和一个匹配串,判定是否能够匹配 * 匹配串中的定义:字符---->字符,*---->0个.1个或者多个字符,?------>对应任意一个字符 * 思路:动态规划:*:dp[i][j] = dp[i][j-1] || dp[i-1][j] * ? || s[i] == p[i]

LeetCode: Wildcard Matching 解题报告

Wildcard MatchingImplement 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)

【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 p