其他分享
首页 > 其他分享> > [LeetCode]10. Regular Expression Matching 动态规划转移方程解析

[LeetCode]10. Regular Expression Matching 动态规划转移方程解析

作者:互联网

题目描述

LeetCode原题链接:10. Regular Expression Matching

Given an input string s and a pattern p, implement regular expression matching with support for '.' and '*' where:

The matching should cover the entire input string (not partial).

Example 1:

Input: s = "aa", p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input: s = "aa", p = "a*"
Output: true
Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

Example 3:

Input: s = "ab", p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".

Example 4:

Input: s = "aab", p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".

Example 5:

Input: s = "mississippi", p = "mis*is*p*."
Output: false

Constraints:

解法:动态规划(c++版)

解法参考 jianchao-li 的帖子

 1 class Solution {
 2 public:
 3     bool isMatch(string s, string p) {
 4         int m = s.size(), n = p.size();
 5         vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
 6         dp[0][0] = true;
 7         for(int i = 0; i <= m; i++) {
 8             for(int j = 1; j <= n; j++) {
 9                 if(p[j - 1] == '*') {
10                     dp[i][j] = dp[i][j - 2] || ( i > 0 && dp[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.'));
11                 }
12                 else {
13                     dp[i][j] = i > 0 && dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
14                 }
15             }
16         }
17         return dp[m][n];
18     }
19 };

思路分析

我们都知道动态规划的核心是找到转移方程:当前状态和上一状态之间的关系。 对于这道题目,我们要先搞清楚两个符号的匹配规则:

jianchao-li的解析刚看有点懵逼,不是很好懂。其实核心思路是用 pattern 去逐位匹配 input string,主要是分为3种情况:

(1)pattern遍历到的字符不是 '*' 时,比较 pattern 和 string「相同位置」的字符是否相等,相等成立的条件是 1-均是相同的字母;2-pattern中对应位置的字符是赖子 '.'

(2)pattern遍历到的字符是 '*' 时,根据 '*' 号的两种作用,又细分为两种情况:

我们用两个指针 i 和 j 分别遍历 input string 和 pattern,注意上面「」中加粗的内容,这关系到条件判断中需要判断的字符or字符串的下标索引位置。当前遍历到的位置的 string 和 pattern 是否能match,取决于上一状态true && 当前位置true。再用表格梳理一下:

代码分析

再回过头来看看 jianchao-li 的帖子,相信开头的这句话 We define dp[i][j] to be true if s[0..i) matches p[0..j) and false otherwise. 肯定给很多人造成了困惑。其实这里前开后闭的区间范围设置遵循了编程中对字符串处理的通用准则:i、j表示结束的位置但是不包含这个位置的字符。可以回忆一下 string::erase(iterator first, iterator last)这个库函数入参的 first 和 last 的含义,是不是一个道理呢?

我们也可以理解为dp[i][j]表示的是string[0, i-1]位置的子串是否和pattern[0, j-1]位置的子串相匹配。

举个

标签:字符,string,10,pattern,Regular,&&,true,Matching,dp
来源: https://www.cnblogs.com/barryyeee/p/15024415.html