leetCode OJ 10. Regular Expression Matching



题意:正则表达式。’.’代表任意字符,’*’代表前一个字符出现任意次。
例如:a*b 匹配ab,aab,aaab,aaaab……


解法一:DFS

1.p.length() == 0
2.p.length() == 1
3.p.charAt(1) != '*'
4.p.charAt(1) == '*'

package edu.jnu;


public class Main {

    public static void main(String[] args) {
	// write your code here
        Main m = new Main();
        System.out.println(m.isMatch("aaba","ab*a*c*a"));
    }
    public boolean isMatch(String s, String p) {

        //p.length() == 0
        if (p.isEmpty())
            return s.isEmpty();


        if (p.length() == 1 || p.charAt(1) != '*') {

            //根据德摩根定律,非(P 或 Q) = (非 P) 且 (非 Q)
            if (s.length() < 1 || (p.charAt(0) != '.' && p.charAt(0) != s.charAt(0)))
                return false;

            return isMatch(s.substring(1), p.substring(1));
        }
        else{
            //从-1开始是因为有 * 匹配 0 个的情况。
            int i = -1;
            while(i < s.length() && (i < 0 || p.charAt(0) == '.' || p.charAt(0) == s.charAt(i)))
                if(isMatch(s.substring(++i),p.substring(2)))
                    return true;

            return false;
        }
    }
}


解法二:DP

设dp[i][j] 表示s串当中以第i个字符结尾的子串,是否与p串当中以第j个字符结尾的子串相匹配,匹配值为1,否则为0。


初始化

1.空字符串s 匹配 空字符串p


2.空字符串p 不能与非空字符串s匹配


3.空字符串s,则下列情况与字符串p匹配



动态转移方程

这里主要针对‘*’进行讨论:

1.p[j] != '*'

如果s[i] == p[j] 或者 p[j] == '.' 

dp[i][j] = dp[i-1][j-1];

下图中蓝色箭头。

2.p[j] == ‘*’

(1)如果‘*’前面的字符x与s串中的字符匹配大于等于一个,并且s[i] == p[j-1] 或者 p[j-1] == '.' ;

dp[i][j] = dp[i-1][j];

下图中绿色箭头。

(2)如果‘*’前面的字符x与s串中的字符匹配的个数为零。

dp[i][j] = dp[i][j-2];

下图中色箭头。


Sample:



对应上面Sample的dp数组:






public boolean isMatch(String s, String p) {

        int sLength = s.length(),pLength = p.length();

        boolean[][] dp = new boolean[sLength+1][pLength+1];

        //空s串 匹配 空p串
        dp[0][0] = true;

        //空p串 不能匹配 非空s串
        for(int i = 1;i <= sLength;i++)
            dp[i][0] = false;

        //只有形式如:a*b*c*…… 的字符串可以匹配空s
        for(int j = 1;j <= pLength;j++){
            if(j > 1 && p.charAt(j-1) == '*')
                dp[0][j] = dp[0][j-2];
        }

        for(int i = 1;i <= sLength;i++){
            for(int j = 1;j <= pLength;j++){
                if(p.charAt(j-1) != '*')
                    dp[i][j] = dp[i-1][j-1] && (s.charAt(i-1) == p.charAt(j-1) || p.charAt(j-1) == '.');
                else
                    dp[i][j] = dp[i][j-2] || (s.charAt(i-1) == p.charAt(j-2) || p.charAt(j-2) == '.') && dp[i-1][j];
            }
        }
        
        return dp[sLength][pLength];

    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值