leetcode10.正则表达式匹配——学习笔记

题目:力扣https://leetcode-cn.com/problems/regular-expression-matching/

class Solution {
    public boolean isMatch(String s, String p) {
        //声明boolean数组dp
        boolean[][] dp = new boolean[s.length()+1][p.length()+1];
        dp[0][0] = true;
        int num=0;
        //初始化处理boolean数组
        for(int i=1;i<s.length()+1;i++){
            dp[i][0] = false;
        }
        for(int j=1;j<p.length()+1;j++){
            if(p.charAt(j-1)=='*'){
                dp[0][j] = dp[0][j-2];
            }else if(p.charAt(j-1)=='.'){
                dp[0][j] = dp[0][j-1];
                num++;
                if(j<p.length()&&p.charAt(j)=='*'){
                    num = 0;
                }
            }else{
                dp[0][j] = false;
            }
        }
        if(num>s.length()){
            return false;
        }
        //根据规则判断T/F
        for(int row=1;row<s.length()+1;row++){
            for(int column=1;column<p.length()+1;column++){
                if(s.charAt(row-1)==p.charAt(column-1) || p.charAt(column-1)=='.'){
                    dp[row][column] = dp[row-1][column-1];
                }else if(p.charAt(column-1)=='*'){
                    if(dp[row][column-2]==true){
                        dp[row][column] = true;
                    }else if(s.charAt(row-1)==p.charAt(column-2)||p.charAt(column-2)=='.'){
                        dp[row][column] = dp[row-1][column];//
                    }
                }else if(s.charAt(row-1)!=p.charAt(column-1)){
                    dp[row][column] = false;
                }
            }
        }
        //返回右下最后一个值
        boolean[] lastrow = dp[dp.length-1];
        return lastrow[lastrow.length-1];
    }
}

 

 思路:用Boolea类型的二维数组记录匹配状态,采用动态规划的方法解题。首先声明一个Boolean类型的二维数组dp,然后对dp进行初始化处理,接着根据状态转移的规则对String s和String p进行匹配,匹配结果填入Boolean二维数组中,直至填完该二维数组,dp最后一个元素的值即是答案,返回即可。

leetcode10.正则表达式匹配例子

(这是一个别人挺nice的训练程序,对状态转移规则不熟悉的时候可以自己用于练习。)

动态规划练习:https://alchemist-al.com/algorithms/regular-expression-matchinghttps://alchemist-al.com/algorithms/regular-expression-matching

1.声明Boolean数组dp。dp[0][0]恒为T,行或者列都需要留空一格,因此数组的长宽分别为s.length()+1和p.length()+1。num是记录出现‘.’的次数,方便后续判断,此处仅仅先声明,具体内容后面再详细说明。

//声明boolean数组dp
boolean[][] dp = new boolean[s.length()+1][p.length()+1];
dp[0][0] = true;
int num=0;

2.初始化处理Boolean数组dp。第0行和第0列留空,因此i和j都是从1开始循环。s位于列,p位于行。记录‘.’的次数,若‘.’后紧跟着‘*’那么则可以将num的值清零,否则一直记录,如果s.length()的值小于num,表示s的长度不够,不可能完成匹配,直接返回false。

//初始化处理boolean数组
for(int i=1;i<s.length()+1;i++){
    dp[i][0] = false;
}
for(int j=1;j<p.length()+1;j++){
    if(p.charAt(j-1)=='*'){
        dp[0][j] = dp[0][j-2];
    }
}else if(p.charAt(j-1)=='.'){
    dp[0][j] = dp[0][j-1];
    num++;
    if(j<p.length()&&p.charAt(j)=='*'){
        num = 0;
    }
}else{
    dp[0][j] = false;
}
if(num>s.length()){
    return false;
}

3.根据规则进行一一判断。将判断的值填入dp二维数组中,直至填满整个数组。因为row和column都是用于表示二维数组位置的,二维数组分别空出一行和一列,因此我们在用row和column作下标表示字符时需要-1处理。以下是具体状态转移规则:

(1)两字符不相同,直接确定为false。‘.’可当作任意字符,即任何字符与‘.’匹配都视作相同。

(2)若两字符相同,则复制dp[row-1][column-1]的值(二维数组中,左上格的值)。

(3)若p.charAt(colunm)的值为‘*’,则查看dp[row][column-2]的值(二维数组中,同一行前两列的值)。如果其值为true,那么直接复制即可,dp[row][column]的值也等于true;如果其值为false,则先对比s.charAt(row-1)【字符串当前字符】与p.charAt(colmn-2)【正则表达式上一字符】的值是否相同,若不同dp[row][column]的值为false;若相同dp[row][column]的值等于dp[row-1][column]的值。

//根据规则判断T/F
for(int row=1;row<s.length()+1;row++){
    for(int column=1;column<p.length()+1;column++){
        if(s.charAt(row-1)==p.charAt(column-1) || p.charAt(column-1)=='.'){
            dp[row][column] = dp[row-1][column-1];
        }else if(p.charAt(column-1)=='*'){
            if(dp[row][column-2]==true){
                dp[row][column] = true;
            }else if(s.charAt(row-1)==p.charAt(column-2)||p.charAt(column-2)=='.'){
                dp[row][column] = dp[row-1][column];//
            }
        }else if(s.charAt(row-1)!=p.charAt(column-1)){
            dp[row][column] = false;
        }
    }
}

4.返回最后答案。声明一个lastrow去接dp二维数组的最后一行,然后去lastrow最后一个元素,它就是答案,最后返回即可。

//返回右下最后一个值
boolean[] lastrow = dp[dp.length-1];
return lastrow[lastrow.length-1];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hokachi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值