java算法&算法思想:10. 正则表达式匹配(动态规划详解)

题目:

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/regular-expression-matching
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:

动态规划
既然是要用到动态规划,那小编就写一下我认为的动态规划的几个步骤:

  1. 设置状态函数f();并明白其作用,一般为前i个的结果是什么。

本题是f(i,j)返回字符串s的前i个字符,字符串p前j个字符的匹配结果

  1. 用状态函数表示要求的结果

字符串s的长度为m,字符串n的长度为n,f(m,n)为要求的结果

  1. 写出状态转移方程,相当于一个递推公式
    在这里插入图片描述
  2. 标注临界值,直接枚举临界的情况
if (i == 0 && j == 0) return true;
else if (j == 0) return false;
else if (i == 0){
     if (j%2 == 0)return p.charAt(j - 1) == '*' && getMN(i, j - 2);
     else return false;
	}
  1. 代码书写,必然会用到递归
  2. 设置缓存,实现代码运行优化

动态规划会涉及很多重复的子问题,如果我们把一些结果缓存起来,在调用之前先看缓存里面有没有,没有再运行,这在遇到重复的地方直接调用缓存就会提高运行速度。

 ArrayList<songsong> arr = new ArrayList<>();
 //缓存的数据结构
   class songsong{
        int i;
        int j;
        boolean okk;
        songsong(int i,int j,boolean okk){
            this.i = i;
            this.j = j;
            this.okk = okk;
        }
    }
    //把结果先缓存,再返回。
  oneArr.okk = result;
        arr.add(oneArr);
        return result;

 //搜索缓存
        for (int k = 0;k<arr.size();k++){
            if (arr.get(k).i == i && arr.get(k).j == j){
                return arr.get(k).okk;
            }
        }

代码:

import java.util.ArrayList;

class Solution {
    String s ;
    String p ;
    ArrayList<songsong> arr = new ArrayList<>();
    public boolean isMatch(String s, String p) {
        this.s = s;
        this.p = p;
        int m = s.length(),n=p.length();
        boolean result = getMN(m, n);
        System.out.println();
        return result;
    }

    private boolean getMN(int i, int j) {
        //临界值
        if (i == 0 && j == 0) return true;
        else if (j == 0) return false;
        else if (i == 0){
            if (j%2 == 0)return p.charAt(j - 1) == '*' && getMN(i, j - 2);
            else return false;
        }

        //搜索缓存
        for (int k = 0;k<arr.size();k++){
            if (arr.get(k).i == i && arr.get(k).j == j){
                return arr.get(k).okk;
            }
        }
        songsong oneArr = new songsong(i,j,false);
        boolean result = true;
        //状态转移方程
        if (p.charAt(j-1) != '*') {
            if (isok(i, j)) {
                result = getMN(i-1,j-1);
            }else {
                result = false;
            }
        }else {
           if (!isok(i,j-1)){
               result= getMN(i,j-2);
           }else {
               result= getMN(i,j-2) || getMN(i-1,j);
           }
        }
        oneArr.okk = result;
        arr.add(oneArr);
        return result;
    }

    private boolean isok(int i, int j) {
        if (p.charAt(j-1)=='.' || s.charAt(i-1) == p.charAt(j-1)) return true;
        else return false;
    }
    class songsong{
        int i;
        int j;
        boolean okk;
        songsong(int i,int j,boolean okk){
            this.i = i;
            this.j = j;
            this.okk = okk;
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

松果Tech

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

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

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

打赏作者

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

抵扣说明:

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

余额充值