题目描述
请实现一个函数用来匹配包含’. ‘和’ * ‘的正则表达式。模式中的字符’.’ 表示任意一个字符,而’ * '表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。
示例 1:
输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。
示例 2:
输入:
s = “aa”
p = “a*”
输出: true
解释: 因为 ‘’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。
示例 3:
输入:
s = “ab”
p = "."
输出: true
解释: "." 表示可匹配零个或多个(’’)任意字符(’.’)。
示例 4:
输入:
s = “aab”
p = “cab”
输出: true
解释: 因为 ‘’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。
示例 5:
输入:
s = “mississippi”
p = "misisp."
输出: false
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母以及字符 . 和 ,无连续的 '’。
链接:https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof
题解:
动态规划,本题与通配符匹配有差距,通配符匹配是*可以匹配任意多个字符包括零个字符,?匹配任意单个字符,而且与模式串中前一个字符没有关系,也就 * 与前一个字符没关系。本题目是 * 指的是前一个字符可以重复多次也包括0次。
p[ j ] 有两种情况:
- p[j]==’ * ’
字母 + 星号的组合在匹配的过程中,本质上只会有两种情况:
1)匹配 s 末尾的一个字符,将该字符扔掉,而该组合还可以继续进行匹配;
2)不匹配字符,将该组合扔掉,不再进行匹配。
如果s[i] ! = p[j-1] 且 p[j-1] 1=‘.’ 那么当下的匹配可以看做是 字母+ 星号没有起作用,那么f[ i ][ j ] =f[ i ][ j-2 ]。
如果s[i] == p[j-1] 要考虑匹配0次到多次 。 例如:“aaa” “aaaa*” 这样还要考虑匹配0次的情况。
f[i][j] = f[i][j-2] || f[i-1][j-2] || f[i-2][j-2] ……|| f[i-k][j-2] (匹配0次||匹配1次)
f[i-1][j] = f[i-1][j-2] || f[i-2][j-2]…
二者合并:f[i][j] = f[i][j-2] || f[i-1][j] - p[j] 是小写字母
f[ i ][ j ] =f[ i-1 ][ j-1 ] 其中s[ i ] = p[ j ] 或者 p[ j ] =’ . ’
class Solution {
public:
bool isMatch(string s, string p) {
s = " " + s;
p = " " + p;
int n = s.size(),m = p.size();
vector<vector<bool>> dp(n+1,vector<bool>(m+1));
dp[0][0]=true;
for (int i = 1; i < n + 1; i++)
{
for (int j = 1; j < m + 1; j++)
{
// 不带 '*' 号时的匹配
if (s[i - 1] == p[j - 1] || p[j - 1] == '.')
{
dp[i][j] = dp[i - 1][j - 1];
}
else if (p[j - 1] == '*')
//暗示了j>=2,真正的字符串j从下标1开始,因此如果j==1,
//那么p[j-1]=" ",则j应该从2开始才进入了真正的字符串
{
// 考虑 '*' 时的两种情况
if (s[i - 1] != p[j - 2] && p[j - 2] != '.')
{
dp[i][j] = dp[i][j - 2];
}
else
{
dp[i][j] = dp[i][j - 2] || dp[i - 1][j];
}
}
}
}
return dp[n][m];
}
};
按照推导的公式的写法,需要在每个字符串前面补充了两个空格,如果只补充一个,对于 p[j]==’*’ 会丢到前面 j =1 以及 j = 0这两种情况,如果在条件中加上j-2>=0的条件的话。
class Solution {
public:
bool isMatch(string s, string p) {
s=" "+s;//增加了两个空格
p=" "+p;
int n = s.size(),m = p.size();
vector<vector<int>> f(n+1,vector<int>(m+1));
f[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(p[j]=='.' ||s[i]==p[j])
{
f[i][j]=f[i-1][j-1];
}
else if(p[j]=='*')
{
if(p[j-1]!='.'&&s[i]!=p[j-1])
f[i][j]=f[i][j-2] ;//匹配0次
else
f[i][j]=f[i][j-2]|| f[i-1][j];//匹配0次或者多次
}
}
}
return f[n][m];
}
};