正则表达式匹配-leetcode Regular Expression Matching

来源:互联网 发布:linux磁盘分区命令 编辑:程序博客网 时间:2024/05/16 07:58

题目:

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

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”, “a*”) → true
isMatch(“aa”, “.*”) → true
isMatch(“ab”, “.*”) → true
isMatch(“aab”, “c*a*b”) → true

递归解法

问题就是正则表达式的匹配,难点在于匹配符*的处理,表示匹配符之前的字母出现次数为0及0次以上,可以将匹配符及其前一个字母看作一个整体进行匹配,所以问题可以分为两个部分:
1.如果模式串当前字符后有匹配符*

while(s.length() > 0 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.')){    //如果s[0]=p[0]或者是p[0]='.',则比较s串和跳过当前字符和*的p子串    //这里的s是表示x*匹配0到多次    if(isMatch(s,p.substring(2)))        return true;    //没有匹配成功,则s串后移一位进行比较    s = s.substring(1);}//当前字符不相等,比较s和跳过当前字符和*的p子串return isMatch(s,p.substring(2));

2.如果模式串当前字符后无匹配符*
没有匹配符*,则递归比较子串即可

if(s.length() == 0)    return false;return (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') && isMatch(s.substring(1),p.substring(1));

整体代码

public boolean isMatch(String s, String p) {        //返回条件,匹配串和模式串都已完成,返回true,匹配串未完则返回false       if(p.length() == 0)           return s.length() == 0;        if(p.length() == 1)            return (s.length() == 1) && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.');        if(p.charAt(1) != '*'){            if(s.length() == 0)                return false;            return (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') && isMatch(s.substring(1),p.substring(1));         }else{            while(s.length() > 0 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.')){                if(isMatch(s,p.substring(2)))                    return true;                s = s.substring(1);            }            return isMatch(s,p.substring(2));        }    }

动态规划解法

使用二维数组dp[i][j]记录s(0,i)和p(0,j)是否匹配,需要解决的问题是求出dp[i][j]和dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1]的关系。通过观察可以发现

public boolean isMatch(String s, String p) {       int m = s.length(),n = p.length();        boolean[][] dp = new boolean[m+1][n+1];        //空串只能匹配空串        dp[0][0] = true;        for(int i = 1;i <= m;i++)            dp[i][0] = false;        //dp[0][j]有真值说明,当前X*匹配了0次        for(int j = 1;j <= n;j++){            dp[0][j] = j > 1 && '*' == p.charAt(j - 1) && dp[0][j-2];        }        for(int i = 1;i <= m;i++){            for(int j = 1;j <= n;j++){                if(p.charAt(j-1) == '*')                    //相当简洁的,只有x*一次都没有匹配(dp[i][j - 2] = 1),当前字符s[i-1]匹配了p[j-2]                    //才能传递dp[i-1][j]的真值                    dp[i][j] = dp[i][j - 2] || (s.charAt(i-1) == p.charAt(j-2) || p.charAt(j-2) == '.') && dp[i-1][j];                else                    //当前字符匹配才能传递dp[i-1][j-1]的真值                    dp[i][j] = dp[i-1][j-1] && (s.charAt(i-1) == p.charAt(j-1) || p.charAt(j-1) == '.');            }        }        return dp[m][n];    }

具体的解法来自http://www.jianshu.com/p/c09c4a3fc14a

阅读全文
0 0
原创粉丝点击