正则表达式匹配
解题思路
- 找到子问题
- if p[i]= s[j] or p[i] ='.' : match(s[0..j-1],p[0..i-1])
else return false - if p[i] = '' : match(s[0..j] ,p[0..i-1]) // is empty
or p[i-1]p[i] = c* , match(s[0..j-x] ,p[0..i-2]) ,
x 代表c* 能最大匹配的长度 '' 'c' ,'cc' 'ccc' , 这里的问题是不定匹配所有的c , 所以用 |=
- 设dp[i][j] = match(s[0..j],p[0..i]) ,从左到右 ,从上到下进行遍历
- 对 dp[i][0]的情况应该 单独初始化,因为 p= "a*" 匹配 s= '' *
- ".*" 都能匹配 "ab" 的话 说明这是一种很强大的组合,应该单独讨论 *
代码
class Solution {
public:
bool isMatch(string s, string p) {
// 找到子问题
// if p[i]= s[j] or p[i] ='.' : match(s[0..j-1],p[0..i-1])
// else return false
// if p[i] = '*' : match(s[0..j] ,p[0..i-1]) //* is empty
//
// or p[i-1]p[i] = c* , match(s[0..j-x] ,p[0..i-2]) ,x 代表c* 能最大匹配的长度 '' 'c' ,'cc' 'ccc'
// 设dp[i][j] = match(s[0..j],p[0..i])
// 从左到右 ,从上到下进行遍历
// 举例验证
// a a a
// 1 0 0 0
// a 0 1 0 0
// b 0 0 0 0
// * 0 1 0 0
// a 0 0 1 0
//程序输出DP
// 1 0 0 0
// 0 1 0 0
// 0 0 0 0
// 0 1 0 0
// 0 0 1 0
std::vector< std::vector<int> > dp(p.size()+1, std::vector<int> (s.size()+1,0));
dp[0][0] =1;
// 应用offset法 s[j] p[i] 对应dp[i+1][j+1]
//如何初始化 dp[n][0]
for(int n=1;n<= p.size() ;n++)
{
// p[n-1] = c or . , dp[n][0] =0
// else * 即 能否与空字符串匹配
// dp[n][0] = dp[n-2][0]
if(n>1 && p[n-1]== '*') dp[n][0] = dp[n-2][0];
else if(p[n-1]== '*') dp[n][0]=1;
else dp[n][0]=0;
}
for(int i=0;i<p.size();i++)
{
for(int j=0;j<s.size();j++)
{
if(p[i]==s[j] || p[i] == '.' )
{
dp[i+1][j+1] = dp[i][j];
}else if(p[i] == '*')
{
// p[i-1] vs s[j] 0 1 ,2
int x=0;
if(i>0) //类似 *ac * 只能匹配0 个 s
{
//关于.* ,如果.只能代表一种字符 如匹配aaa VS .*
// char target=p[i-1];
// if(p[i-1] == '.') target=s[j]; // 寻找 s[...j] 第一个不等于s[j]
// int tJ = j;
// while(tJ>=0 && s[tJ] == target )
// {
// x++;
// tJ--;
// }
//但".*" 都能匹配 "ab" 的话 说明这是一种很强大的组合
if(p[i-1] == '.')
{
// 尝试找到 dp[i-2][j-y]
// 其中y 1 0 0 0 第一个1出现的位置
// 即如果 发现dp[i-2][...j)] 中有1存在 则 dp[i][j]=1
int m=j+1;
for(;m>=0;m--)
{
if(dp[i-1][m]) break;
}
if(m<0) dp[i+1][j+1]=0;
else dp[i+1][j+1]=1;
}else
{
int tJ = j;
//这里的问题是不定匹配所有的c , 所以用 |=
while(tJ>=0 && s[tJ] == p[i-1] )
{
dp[i+1][j+1] |= dp[i-1][j+1-x];
x++;
tJ--;
}
dp[i+1][j+1] |= dp[i-1][j+1-x];
}
}else dp[i+1][j+1] = dp[i-1][j+1-x];
}else
{
dp[i+1][j+1] =0;
}
}
}
// for(auto vec: dp)
// {
// for(auto x: vec) std::cout<< x <<" ";
// std::cout << std::endl;
// }
return dp[p.size()][s.size()];
//eg2
// a b
// 1 0 0
// . 0 1 0
// * 0 1 1
//eg3
// a a b
// 1 0 0 0
// c 0 0 0 0
// * 1
// a
// *
// b
// *
//exe output
// 1 0 0 0
// 0 0 0 0
// 1 0 0 0
// 0 1 0 0
// 1 1 1 0
// 0 0 0 1
}
};
题目描述
请实现一个函数用来匹配包含'. '和''的正则表达式。模式中的字符'.'表示任意一个字符,而''表示它前面的字符可以出现任意次(含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 的小写字母以及字符 . 和 ,无连续的 ''。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。