标签:match 枚举 ++i 转移 解决 turn 多个 class 美的
实现一个支持.
和*
的正则表达式匹配。其中.
匹配任意单个字符,*
匹配0或多个前面的那一个元素。
给出两个字符串s
和p
,前者只包含从a-z
的小写字母,后者只包含从a-z
的小写字母和两个匹配字符,问是否匹配。
return regex_match(s, regex(p));
*
,那直接写就可以了。其实多的*
这个符号,无非就是将前一个字符变为了0道多个,通过递归枚举每种情况,轻松解决。时间复杂度:很大。p[i][j]
表示s
串[0,i]
与p
串[0,j]
匹配的结果。
s[i] == p[j] || p[j] == ‘.‘
时,dp[i][j] = dp[i-1][j-1]
。s[i] != p[j]
时,可能发生匹配的情况只有p[j] == ‘*‘
,此时所有可能如下:
*
前的字符与对应位置字符无法匹配,此时只能使其出现0次才可继续匹配,即dp[i][j] = dp[i][j - 2]
。*
前的字符与对应位置字符可匹配,此时*
可以匹配多个、1个或0个,即dp[i][j] = dp[i - 1][j] || dp[i][j - 1] || dp[i][j - 2]
。dp
数组就都初始化为了0。代码0:
class Solution {
public:
bool isMatch(string s, string p) {
return regex_match(s, regex(p));
}
};
代码1:
class Solution {
public:
bool isMatch(string s, string p) {
if(p.size() == 0) return s.size() == 0;
bool first = (s.size() && (s[0] == p[0] || p[0] == '.'));
if(p.size() >= 2 && p[1] == '*')
return isMatch(s, p.substr(2)) || (first && isMatch(s.substr(1), p));
else
return first && isMatch(s.substr(1), p.substr(1));
}
};
代码2:
class Solution {
public:
bool isMatch(string s, string p) {
int lens = s.size(), lenp = p.size();
bool dp[lens + 1][lenp + 1];
for(int i = 0; i <= lens; ++i)
for(int j = 0; j <= lenp; ++j)
dp[i][j] = 0;
dp[0][0] = 1;
if(lenp > 1)
{
for(int i = 1; i < lenp; i += 2)
if(p[i] == '*')
dp[0][i + 1] = dp[0][i - 1];
}
for(int i = 1; i <= lens; ++i)
{
for(int j = 1; j <= lenp; ++j)
{
if(s[i - 1] == p[j - 1] || p[j - 1] == '.')
dp[i][j] = dp[i - 1][j - 1];
else if(j > 1 && p[j - 1] == '*')
{
if(p[j - 2] != s[i - 1] && p[j - 2] != '.')
dp[i][j] = dp[i][j - 2];
else
dp[i][j] = dp[i - 1][j] || dp[i][j - 1] || dp[i][j - 2];
}
}
}
return dp[lens][lenp];
}
};
DP是很优美的思路,关键在于建立状态转移方程,多加练习可培养。
标签:match 枚举 ++i 转移 解决 turn 多个 class 美的
原文地址:https://www.cnblogs.com/songjy11611/p/12235200.html