leetcode难题之Regular Expression Matching

一,题目简述

Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.

'.' Matches any single character.
'*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

字符串匹配问题:

给定字符串str,其中绝对不含有字符'.'和'*'。再给定字符串pattern,其中可以含有'.'或'*','*'字符不能是pattern的首字符,并且任意两个'*'字符不相邻。
pattern中的'.'代表任何一个字符
pattern中的'*'表示前一个字符可以有0或多个。
请写一个函数,判断str是否被pattern匹配。

二,题目分析

字符串匹配问题,题中给了两个特殊的模式符号'.'和'*',理解他们的含义然后暴力判断字符串就好。重点在于读题审题理解题意,然后多学多做。

三,题目解答

递归版:

class Solution {
    public boolean isMatch(String s, String p) {
        if(s == null || p == null)
            return false;
        char[] str = s.toCharArray();
        char[] pat = p.toCharArray();
        return isValid(str, pat) ? process(str, pat, 0, 0):false;
    }
    
    public boolean isValid(char[] s, char[] p){//判断输入是否有效
        for(int i = 0; i < s.length; i++){
            if(s[i] == '*' || s[i] == '.')
                return false;
        }
        for(int i = 0; i < p.length; i++){
            if(p[i] == '*' &&(i == 0 || p[i-1] == '*'))
                return false;
        }
        return true;
    }
    
    public boolean process(char[] s, char[] p, int si, int pi){//判断是否匹配
        if(pi == p.length)
            return si == s.length;
        if(pi +1  == p.length || p[pi+1] != '*'){
            return si != s.length && (p[pi] == s[si] || p[pi] == '.') && process(s,p,si+1,pi+1);
        }
        while(si != s.length && (p[pi] == s[si] || p[pi] == '.')){
            if(process(s,p,si,pi+2))
                return true;
            si++;
        }
        return process(s,p,si,pi+2);
    }
}

首先,isValid函数判断输入是否有效,即字符串s不能包含'*'和'.',字符串p中'*'字符前不能为空或者字符'*'

判断函数process用递归判断,pi,si分别标识字符串p和s的所在位置,即判断字符串p的pi位置之后的字符串是否能模式识别字符串s的si位置之后的字符串。

如果p的pi+1位置不是'*'的话,只需要判断现在所处的字符是否匹配,并且再继续往下判断si+1和pi+1位置后的字符串。

如果p的pi+1位置是'*'的话,两种情况:一是'*'代表0次,我们判断p的pi+2位置之后和s的si位置之后即可;二是'*'代表非0次,我们保持pi不动,si向后移直到跳出循环即可。

扫描二维码关注公众号,回复: 6028601 查看本文章

非递归版

同理我们可以用深度搜索代替递归,额外空间复杂度一个布尔数组dp[i][j]表示字符串s的i位置之后部分和p的j位置之后的部分是否匹配。

class Solution {
    public boolean isMatch(String s, String p) {
        if(s == null || p == null)
            return false;
        char[] str = s.toCharArray();
        char[] pat = p.toCharArray();
        if(!isValid(str, pat))
            return false;
        boolean[][] dp = initDpMap(str, pat);
        for(int i = str.length-1; i > -1; i--){
            for(int j = pat.length-2; j > -1; j--){
                if(pat[j+1] != '*'){
                    dp[i][j] = (str[i] == pat[j] || pat[j] == '.')&&dp[i+1][j+1];
                }else{
                    int si = i;
                    while(si != str.length &&(str[si] == pat[j] || pat[j] == '.')){
                        if(dp[si][j+2]){
                            dp[i][j] = true;
                            break;
                        }
                        si++;
                    }
                    if(dp[i][j] != true){
                        dp[i][j] = dp[si][j+2];
                    }
                }
            }
        }
        return dp[0][0];
    }
    
    public boolean[][] initDpMap(char[] s, char[] p){
        int slen = s.length;
        int plen = p.length;
        boolean[][] dp = new boolean[slen+1][plen+1];
        dp[slen][plen] = true;
        for(int i = plen-2; i > -1; i--){
            if(p[i] != '*' && p[i+1] == '*'){
                dp[slen][i] = true;
            }else
                break;
        }
        if(slen > 0 && plen > 0){
            if(p[plen-1] == '.' || s[slen-1] == p[plen-1]){
                dp[slen-1][plen-1] = true;
            }
        }
        return dp;
    }
    
    public boolean isValid(char[] s, char[] p){//判断输入是否有效
        for(int i = 0; i < s.length; i++){
            if(s[i] == '*' || s[i] == '.')
                return false;
        }
        for(int i = 0; i < p.length; i++){
            if(p[i] == '*' &&(i == 0 || p[i-1] == '*'))
                return false;
        }
        return true;
    }
}

四,题目回忆

字符串问题的两大处理情景,带字符串下标的递归和借助布尔数组的dp。可以归纳出字符串处理的问题。

猜你喜欢

转载自blog.csdn.net/wannuoge4766/article/details/89211379