题目描述:
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
解答:
分析:根据题目意思 '.' 可以表示任意字符,也就是说'.'可以匹配s中任意字符。'*'取决于前一个字符,所以可以把a*这样的字符看着整体。那么题目要求的意思是。字符串s与p相匹配,也就是将'.'和'*'进行转换后s=p,这里举两个例子:
1.s="aa",p="a*" 这里把a*看着一个整体,它所表达的意思就是多个a,但也可以是0个a也就是空字符,所以把a*看着aa,即可与s匹配。
2.s="aaa",p="a*b*ac*a" 这里把a*看着a,b*看着空字符,c*也看着空字符,就变成了aaa,所以p也可以等于aaa。因此这个题的关键点就在于处理像a*这样的整体,该怎么变他们才能与s匹配。
那么我们可以用动态规划的状态转移思维来想。设状态dp[i][j]为s的前i个字符与p的前j个字符是否相匹配。设初始状态dp[0][0]=1表示前0个,也就是空字符状态下两个字符一定匹配。
现在初始状态知道了,中间状态的递推式该怎么去推,这是一个难点。可以先分情况讨论
第一种情况最简单,当s[j-1]=p[j-1] or p[j-1]='.'时(注:由于 i 和 j 表示的是前 i 或者前 j 个字符,所以第i个字符的下标就是i-1),也就是在第 i 个字符和第 j 个字符相等时。那么dp[i][j]=dp[i-1][j-1]。(在s的第i个字符与p的第j个字符相等时,那么当前字符串是否匹配取决于前i-1个和前j-1个字符串是否匹配)
第二种情况 就是s[j-1]!=p[j-1] 且p[j-1]!='.'时 这个时候就需要判断p[j-1]是否为'*'.如果不是,那就可以直接断定不匹配了。
如果p[j-1]=*。dp[i][j]该怎么往前推算呢。 我举个例子。
s="aaa",p="a*b*aa*"
我们前面说了像 a*这样的看着一个整体,表示n个a。
我们在遇到p[j-1]=*时,就需要判断 if(p[j-2]==s[j-1]) 则 说明这个整体可以匹配,但是要把他当作多个来匹配还是只当中一个来匹配,还是直接不匹配。其实这不是一个选择,这三种情况都可以。
如果看着多个来匹配,就有 dp[i][j]=dp[i-1][j]。这里为什么j没有减一。因为看着多个字符后,第j个字符是*。你移动后就不在是*,就不在是多个前面哪一个字符了。
如果看着一个字符来匹配。dp[i][j]=dp[i-1]dp[j-2]。这里j-2 就是*和前面那个字符看成了一个字符来匹配。
如果看着空字符,也就是不匹配。dp[i][j]=dp[i][j-2]。这里不减一是因为不匹配。
这三种情况都可以。所以选择其中一种能够使整个字符串都能够匹配上的方案,如果都匹配不上那就是不匹配了。
if(juge(s[i-1],p[j-2]))//如果判断出前一个字符匹配,将这三种情况全部判断一遍直到判断出能够全部匹配的状态即dp[i][j]==1。
{
dp[i][j]=dp[i-1][j];
if(dp[i][j]==0)
{
dp[i][j]=dp[i-1][j-2];
if(dp[i][j]==0)
{
dp[i][j]=dp[i][j-2];
}
}
}
全部代码
class Solution {
public:
bool juge(char a,char b)//判断两个字符是否匹配
{
if(a==b||b=='.')//只要两个字符相等,或者p的字符为.就匹配返回真
{
return true;
}
return false;
}
bool isMatch(string s, string p) {
int m=s.size();
int n=p.size();
vector<vector<int>> dp(m+1,vector<int>(n+1));
dp[0][0]=1;
for(int i=0;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(i==0)//当s为空的情况下,p不为空,但是有*可以使前一个字符为空。
{
if(p[j-1]=='*')
{
dp[i][j]=dp[i][j-2];
}
}
else if(p[j-1]=='*')
{
dp[i][j]=dp[i][j-2];//如果*的前一个字符不匹配,j前进两位,*和前一个字符看着空字符
if(juge(s[i-1],p[j-2]))//如果匹配,判断3种情况
{
dp[i][j]=dp[i-1][j];
if(dp[i][j]==0)
{
dp[i][j]=dp[i-1][j-2];
if(dp[i][j]==0)
{
dp[i][j]=dp[i][j-2];
}
}
}
}
else //最简单的情况
{
if(juge(s[i-1],p[j-1]))
{
dp[i][j]=dp[i-1][j-1];
}
}
}
}
return dp[m][n];
}
};