LeetCode010 Regular Expression Matching 解析

详细见:leetcode.com/problems/regular-expression-matching/

说明: 回溯版本好理解,DP版本解释如下:

建立行len(s)+1和列len(p)+1的dp矩阵

dp[i+1][j+1]代表s[0,i]和p[0,j]的匹配结果。

有两种匹配上情况:

1,字符相同或者p是'.'

2,p是'*',有匹配0次,匹配1次,匹配多次三种情况


Java Solution: github

package leetcode;

import java.util.ArrayList;

public class P010_RegularExpressionMatching {
	/*
	 * 	33.84% 
	 * 	97ms
	 */
	static class Solution2 {
		public boolean isMatch(String s, String p) {
			if (s == null)
				return p == null;
			if (p == null)
				return s == null;
			return isMatch(s, 0, s.length(), p, 0, p.length());
		}
		private boolean isMatch(String s, int i, int I, String p, int j, int J) {
			if (getChar(p, j, J) == '\0')	return getChar(s, i, I) == '\0';
			if (getChar(p, j + 1, J) == '*') {
				while (getChar(s, i, I) == getChar(p, j, J) || (getChar(p, j, J) == '.' && getChar(s, i, I) != '\0')) {
					if (isMatch(s, i ++, I, p, j + 2, J))
						return true;
				}
				return isMatch(s, i, I, p, j + 2, J);
			} else {
				if (getChar(s, i, I) == getChar(p, j, J) || (getChar(p, j, J) == '.' && getChar(s, i, I) != '\0'))
					return isMatch(s, i + 1, I, p, j + 1, J);
				return false;
			}
		}
		private char getChar(String str, int i, int I) {
			if (i >= I)
				return '\0';
			else
				return str.charAt(i);
		}
	}
	static class Solution8 {
	    public boolean isMatch(String s, String p) {
	        if (s == null) return p == null;
	        int sn = s.length(), pn = p.length();
	        boolean[][] m = new boolean[sn + 1][pn + 1];
	        m[0][0] = true;
	        for (int pi = 0; pi < pn; pi ++)
	            if (p.charAt(pi) == '*' && m[0][pi - 1])
	                m[0][pi + 1] = true;
	        for (int si = 0; si < sn; si ++) {
	            for (int pi = 0; pi < pn; pi ++) {
	                char sc = s.charAt(si), pc = p.charAt(pi);
	                if (sc == pc || '.' == pc) {
	                    m[si + 1][pi + 1] = m[si][pi];     //匹配1次
	                } else if (pc == '*' ) {
	                    //[pi-1, pi]结成共同体
	                    if (sc == p.charAt(pi - 1) || '.' == p.charAt(pi - 1)) {
5	                        m[si + 1][pi + 1] = 
	                                m[si][pi + 1] ||       //匹配很多次 s[si]和{p[pi-1], p[pi]}已经匹配上
	                                                       //肯定s[0,si-1]还要和p[0,pi]去匹配嘛
	                                m[si + 1][pi - 1] ||   //匹配0次    按照道理应该是s[0,si]和p[0,pi-2]去匹配
	                                m[si][pi - 1];         //匹配1次    s[si]和{p[pi-1], p[pi]}匹配上
	                                                       //就是看,s[0,si-1]和p[0,pi-2]是否能够匹配上
	                    } else {
	                        m[si + 1][pi + 1] = m[si + 1][pi - 1];     //只能匹配0次
	                    }
	                } else {
	                    m[si + 1][pi + 1] = false;
	                }
	            }
	        }
	        return m[sn][pn];
	    }
	}
}


C Solution: github

/*
    url: leetcode.com/problems/regular-expression-matching/
    _match:     64ms  6.40%
    _match_dp:   9ms 83.74%
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define bool int
#define true 1
#define false 0

char _access_char_array(char *s, int sn, int i) {
    if (i >= sn) return '\0';
    return *(s + i);
}

bool _judge(char sc, char pc) {
    return sc == pc || (pc == '.' && sc != '\0');
}

//use trace back
bool _match(char* s, int sn, int si, char* p, int pn, int pi) {
    char sc = _access_char_array(s, sn, si);
    char pc = _access_char_array(p, pn, pi);
    if (pc == '\0') return sc == '\0';
    if (_access_char_array(p, pn, pi + 1) == '*') {
        while (_judge(sc, pc)) {
            if (_match(s, sn, si, p, pn, pi + 2))
                return 1;
            sc = _access_char_array(s, sn, ++ si);
        }
        return _match(s, sn, si, p, pn, pi + 2);
    }
    return _judge(sc, pc) && _match(s, sn, si + 1, p, pn, pi + 1);
}

//use dp
bool _match_dp(char* s, char* p) {
    int sn = strlen(s), pn = strlen(p);
    int si = 0, pi = 0;
    int sic = 0;
    char sc = '\0', pc = '\0';
    char ** dp = (char **) malloc(sizeof(char *) * (sn + 1));
    for (si = 0; si < sn + 1; si ++)
        * (dp + si) = (char *) malloc(sizeof(char) * (pn + 1));
    for (si = 0; si < sn + 1; si ++)                //set default 0
        memset(*(dp + si), 0, pn + 1);              //diff with java
    **dp = 1;                                       //""(p) match ""(s)
    for (si = 0, pi = 0; pi < pn; pi ++) {
        if (*(p + pi) == '*' && *(*(dp + si) + pi - 1)) {
            *(*(dp + si) + pi + 1) = 1;             //how p match ""(s)
        }
    }
    for (si = 0; si < sn; si ++) {
        for (pi = 0; pi < pn; pi ++) {
            if (*(s + si) == *(p + pi) || *(p + pi) == '.') {
                *(*(dp + si + 1) + pi + 1) = *(*(dp + si) + pi);
            } else if (*(p + pi) == '*') {
                if (*(p + pi - 1) != *(s + si) && *(p + pi - 1) != '.') //only use zero
                    *(*(dp + si + 1) + pi + 1) = *(*(dp + si + 1) + pi - 1);
                else
                    *(*(dp + si + 1) + pi + 1) = 
                        *(*(dp + si) + pi + 1) ||       //* use many times
                        *(*(dp + si + 1) + pi) ||       //* use zero times
                        *(*(dp + si + 1) + pi - 1);     //* use one time
            } else {
                *(*(dp + si + 1) + pi + 1) = 0;         //p[0,pi] can not match s[0,si]
            }
        }
    }

    //ans
    sic = *(*(dp + sn) + pn);
    for (si = 0; si < sn + 1; si ++)
        free(*(dp + si));
    free(dp);
    return sic;
}

bool isMatch(char* s, char* p) {
    if (s == NULL || p == NULL) return s == NULL && p == NULL;
    return _match(s, strlen(s), 0, p, strlen(p), 0);
}



int main() {
    
    char *s = "aa";
    char *p = "aa";
    printf("answer is %d\r\n", isMatch(s, p));
    printf("dp answer is %d\r\n", _match_dp(s, p));
    return 0;
}


Python Solution: github

#coding=utf-8

'''
    url: leetcode.com/problems/regular-expression-matching/
    @author:     zxwtry
    @email:      zxwtry@qq.com
    @date:       2017年3月27日
    @details:    BackTraceSolution: TLE
    @details:    DPSolution: AC 99ms 67.25%
'''

class DPSolution(object):
    def isMatch(self, s, p):
        I = 0 if s == None else len(s)
        J = 0 if p == None else len(p)
        m = [[False for i in range(J + 1)] for j in range(I + 1)]
        m[0][0] = True
        for j in range(J):
            if '*' == p[j] and m[0][j - 1]:
                m[0][j + 1] = True
        for i in range(I):
            for j in range(J):
                if s[i] == p[j] or '.' == p[j]:
                    m[i + 1][j + 1] = m[i][j]
                elif p[j] == '*':
                    if s[i] != p[j - 1] and '.' != p[j - 1]:
                        m[i + 1][j + 1] = m[i + 1][j - 1]
                    else:
                        m[i + 1][j + 1] = \
                        m[i][j + 1] or\
                        m[i][j - 1] or\
                        m[i + 1][j - 1]
                        #[p[j - 1],p[j]]组成一组
                        #匹配多次,看s[0,i-1]和p[0,j]是否能够匹配
                        #匹配一次,看s[0,i-1]和p[0,j-2]是否能够匹配
                        #匹配0次,看s[0,i]和p[0,j-2]是否能够匹配
                else:
                    m[i + 1][j + 1] = False
        return m[I][J]
               
class BackTraceSolution(object):
    def a(self, s, i, l):
        return s[i] if  i < l else '\0'
    def m(self, s, i, I, p, j, J):
        sc, pc = self.a(s, i, I), self.a(p, j, J)
        if pc == '\0': return sc == '\0'
        if self.a(p, j + 1, J) == '*':
            while sc == pc or (pc == '.'and sc != '\0'):
                i += 1
                sc = self.a(s, i, I)
                if self.m(s, i - 1, I, p, j + 2, J):
                    return True
            return self.m(s, i, I, p, j + 2, J)
        else:
            if sc == pc or (pc == '.' and sc != '\0'):
                return self.m(s, i + 1, I, p, j + 1, J)
            return False
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        I = 0 if s == None else len(s)
        J = 0 if p == None else len(p)
        return self.m(s, 0, I, p, 0, J)

if __name__ == "__main__":
    s = "baccbbcbcacacbbc"
    p = "c*.*b*c*ba*b*b*.a*"
    print(DPSolution().isMatch(s, p))







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值