首页 > 其他分享 >【动态规划】正则表达式

【动态规划】正则表达式

时间:2024-01-22 15:56:02浏览次数:37  
标签:字符 匹配 正则表达式 ne 字符串 cases 动态 规划 dp

目录

1. 题目

题目列表:

序号 题目 难度
1 10. 正则表达式匹配 困难

2. 应用

2.1. Leetcode 10. 正则表达式匹配

题目

10. 正则表达式匹配

解题思路

设 \(dp[i][j]\) 表示 \(s\) 的前 \(i\) 个字符与 \(p\) 的前 \(j\) 个字符是否匹配,即子串 \(s[0 \cdots i-1]\) 与子串 \(p[0 \cdots j-1]\) 是否匹配。

显然,当两个字符串的长度都是零时,它们可以匹配成功,因此,边界条件:

\[dp[0][0] = true \]

通过分析,容易看出来:

  • 如果模式串 \(p\) 的某一个位置是一个普通字符(字母或者点号)时,它只能匹配字符串 \(s\) 中的一个字符;

  • 如果模式串 \(p\) 的某一个位置是一个星号字符时,它可以多次匹配 \(s\) 中的多个相同的字符。

因此,对于 \(s[0 \cdots i-1]\) 和 \(p[0 \cdots j-1]\) 的最后一个字符,有三种情况:

  • 当 \(p[j-1]\) 是字母时:

    • 如果当前两个字符相等,即 \(s[i-1] = p[j-1]\),那么,当前状态可以通过前一个状态转移得到,即

      \[dp[i][j] = dp[i-1][j-1], \ s[i-1] = p[j-1] \]

    • 如果当前两个字符不相等,即 \(s[i-1] \ne p[j-1]\),那么,两个字符串就不匹配,即

      \[dp[i][j] = false, \ s[i-1] \ne p[j-1] \]

    因此,当 \(p[j-1]\) 是字母时,其状态转移方程为:

    \[dp[i][j] = \begin{cases} dp[i-1][j-1], &s[i-1] = p[j-1]\\ false, &s[i-1] \ne p[j-1] \end{cases} \]

  • 当 \(p[j-1]\) 是 * 时,那么,它可以对字符串 \(s\) 匹配任意次:

    • 如果星号匹配零次,即星号没有匹配到字符串 \(s\) 中的字符,那么,它可以通过前一个状态转移得到

      \[dp[i][j] = dp[i][j-2], \ s[i-1] \ne p[j-2] \]

    • 如果星号匹配多次,那么,此时有两种情况:

      • 当前匹配成功,即消耗了一个字符串 \(s\) 中的字符 \(s[i - 1]\),当前状态与前一个状态的相同;

      • 当前匹配失败,此时,需要去掉模式串 \(p\) 中的 字母 + 星号 组合。

      上述两种情况,只要有一种情况匹配成功即可。

      \[dp[i][j] = dp[i-1][j] \lor dp[i][j-2], \ s[i-1] = p[j-2] \]

      注意:这里 \(\lor\) 表示逻辑或。

    因此,当 \(p[j-1]\) 是字母时,其状态转移方程为:

    \[dp[i][j] = \begin{cases} dp[i-1][j] \lor dp[i][j-2], &s[i-1] = p[j-2]\\ dp[i][j-2], &s[i-1] \ne p[j-2] \end{cases} \]

  • 当 \(p[j-1]\) 是 . 时,那么,它可以成功匹配字符串 \(s\) 中的任意字符;

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

综上,状态转移方程为:

\[dp[i][j] = \begin{cases} dp[i-1][j-1], & p[j-1] \ne * ,match(s[i-1], p[j-1]) = true\\ false, & p[j-1] \ne * ,match(s[i-1], p[j-1]) = false \\ dp[i-1][j] \lor dp[i][j-2], & p[j-1] = * , match(s[i-1], p[j-2]) = true\\ dp[i][j-2], & p[j-1] = * , match(s[i-1], p[j-2]) = false \end{cases} \]

注意:长度为零的模式串不能匹配任何字符串。

代码实现

class Solution {
    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 = 0; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (p.charAt(j - 1) == '*') {
                    dp[i][j] |= dp[i][j - 2];
                    if (match(s, i, p, j - 1)) {
                        dp[i][j] |= dp[i - 1][j];
                    }
                } else {
                    if (match(s, i, p, j)) {
                        dp[i][j] |= dp[i - 1][j - 1];
                    }
                }
            }
        }
        return dp[m][n];
    }

    private boolean match(String s, int i, String pattern, int j) {
        // 判断s[i - 1]与p[j - 1]是否匹配
        if (i == 0) {
            return false;
        }
        if (pattern.charAt(j - 1) == '.') {
            return true;
        }
        return s.charAt(i - 1) == pattern.charAt(j - 1);
    }
}

标签:字符,匹配,正则表达式,ne,字符串,cases,动态,规划,dp
From: https://www.cnblogs.com/larry1024/p/17979801

相关文章

  • 深入分析若依数据权限@datascope (注解+AOP+动态sql拼接) 【循序渐进,附分析过程】
    除了我们平时都知道的路由权限(即对接口的访问权限外),在日常生产开发中,我们还应该有对数据的访问权限。在若依这个框架中,通过角色中的数据范围这个属性来对数据权限进行控制。对应实体类:深入分析一个用户肯定是有一种角色的,也肯定是隶属于一个部门的。这里咱们就以用户在......
  • 动态规划(9) 编辑距离最终版
    目录115不同的子序列583.两个字符串的删除操作编辑距离115不同的子序列dp数组的含义:dp[i][j]以i-1结尾的s中包含有多少个以j-1为结尾的tdp初始化:dp[0][0]空字符串中有多少个空字符串,显然1个dp[i][0]以i-1为结尾的s中包含有多少个空字符串,也是1个递推公式:显然需要考虑s[i......
  • 动态规划(8) 编辑距离
    目录1035不相交的线53最大子数组和392判断子序列1035不相交的线弄清楚在求什么,实际上是在求最长公共子序列classSolution{public:intmaxUncrossedLines(vector<int>&nums1,vector<int>&nums2){intn=nums1.size();intm=nums2.size();......
  • [转]一篇搞懂javascript正则表达式
    原文地址:一篇搞懂javascript正则表达式-知乎最近在看vue源码的时候发现一个令人头疼的问题,就是正则表达式,在此之前我对正则只有一知半解,没有深入了解,所以看到正则高级写法都不知是什么含义,哎...,所以就去查看相关资料和博主写的,特意整理记录一下学习的过程并用通俗易懂的文章分......
  • 动态规划- leecode 122
    Problem:122.买卖股票的最佳时机II目录思路解题方法复杂度Code思路仍然是一道比较简单的动态规划,但是一上手做还是没理清楚状态是什么。一天的状态只有两种,持有股票和没有股票,这样就可以列出状态转移方程\(dp[i][j]=max(dp[i-1][j],dp[i-1][j*]+或-price[i])\),这里的j表......
  • Jmeter 之正则表达式的使用
    1背景及用途:html、json数据都可以转化为文本,提供给正则去提取,使用正则可以提取全部数据,这就是正则表达式非常强大的一点。html格式响应更适合用xpath提取,性能比正则好一点json格式响应数据适合用jsonpath来提取,性能比正则好一点 2正则表达式介绍:  3添加......
  • 二维动态规划+子集和
    题目:查看代码#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;constintN=1e3+7;constllmod=1e5+7;intn,s;intdp[N][N],a[N];intmain(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n;for(in......
  • 模拟jdk动态代理(完整版)
    实现思路1:定义一个字符串s2:加载s利用流生成对应的java文件3:通过类加载器加载java文件生成class文件4:通过class生成代理对象5:测试成功我使用过jdk代理的场景1:通过拦截request对象,代理其中的get参数的方法来过滤敏感词2:通过阅读aop源码发现,底层用的也是动态代理(jdk,cglib)3:jdk代......
  • Qt如何调用VS编写的动态链接库(dll文件)
     下面是我在VS编译器上写的一个简单的dll文件,关于dll文件如何编写,我就不再赘述了。.h文件#ifndef_MYDLL_H#define_MYDLL_H#ifdefMYDLL_EXPORTS#defineMYDLL_API__declspec(dllexport)#else#defineMYDLL_API__declspec(dllimport)#endifextern"C"MYDLL_......
  • 动态规划--摆花(二维dp)
    #include<iostream>usingnamespacestd;//dp[i][j]表示第i种花位置,第j个位置为止longlongintdp[120][120];longlonginta[160];intmain(){intn,m;cin>>n>>m;//n种花m盆for(inti=1;i<=n;i++){cin>>a[i];}dp[0][0]=1;for(inti=1;i<=n;......