给定一个字符串 (s
) 和一个字符模式 (p
)。实现支持 '.'
和 '*'
的正则表达式匹配。
'.' 匹配任意单个字符。 '*' 匹配零个或多个前面的元素。
匹配应该覆盖整个字符串 (s
) ,而不是部分字符串。
说明:
s
可能为空,且只包含从a-z
的小写字母。p
可能为空,且只包含从a-z
的小写字母,以及字符.
和*
。
示例 1:
输入: s = "aa" p = "a" 输出: false 解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入: s = "aa" p = "a*" 输出: true 解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"。
示例 3:
输入: s = "ab" p = ".*" 输出: true 解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:
输入: s = "aab" p = "c*a*b" 输出: true 解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入: s = "mississippi" p = "mis*is*p*." 输出: false
思路:如果不用递归的方法,一点一点的判断,比如如果当前的p[j]为*,那么如果s的当前值与p[j-1]相等,就i++。这样存在的问题是,不能判断出*到底代替几个p[j-1],所以我们还是用递归的方法。
bool isMatch(string s, string p) { int pLen=p.length(); int sLen=s.length(); if(pLen==0) return sLen==0; if(pLen==1) if( (s[0]==p[0] || p[0]=='.') && sLen==1) return true; else return false; if(p[1]!='*') { if(s.length()>0 && (s[0]==p[0] || p[0]=='.')) return isMatch(s.substr(1),p.substr(1)); else return false; } else { while(s.length()>0 && (p[0]==s[0] || p[0]=='.')) { if(isMatch(s,p.substr(2)))//*表示0个字符 return true; s=s.substr(1); } return isMatch(s,p.substr(2)); } }
上述程序就将*分成了两种情况,一种是*代表0个字符,一种是*代表1个或多个字符。首先每次判断代表0个字符是否符合,如果不符合,那么就先代表一个,将s的首字符去掉,接着判断,这样*就代表了一个或多个。
还有一种DP的思路,是用空间换时间。额外申请一个数组作为辅助,记录前面的结果。dp[i][j]代表s[0..i-1]和p[0...j-1]的匹配,0代表匹配失败,1代表匹配成功。那么可以得到,dp[0][0]=1表示空串与空串是匹配的,dp[i][0]=0,表示如果p是空串,那么一定不匹配。dp[0][j]表示s是空串,这种情况如果p是x*的组合,是可以匹配的,否则匹配失败。而且dp[0][1]=0表示如果s为空串,p只有一个字符时,肯定匹配失败。dp[i][j]我们可以分为p[j-1]为*和不为*的情况,(1)如果p[j-1]也就是p的最后一个元素为*,那么还可以分为它代表0个前面的元素,也就是说s[0..i-1]与p[0..j-3]是要匹配的,即dp[i][j-2]=1。或者它代表一个或多个前面的元素,那么s[0..i-2]与p[0..j-1]是匹配的,并且s的最后一个元素s[i-1]还要与p的倒数第二个相等,即s[i-1]==p[i-2].
bool isMatch(string s, string p) { int m=s.size()+1,n=p.size()+1; vector<vector<bool> > dp(m,vector<bool>(n)); dp[0][0] = true;//s无字符,p无字符 dp[0][1] = false;//s无字符,p有一个字符(且不能省略) for (int i = 1; i <= s.size(); ++i) dp[i][0] = false;//s有字符,p无字符 for (int j = 2; j <= p.size(); ++j)//Ax*只有A与空串匹配,且后两个字符是x*的形式才匹配 dp[0][j] = (p[j - 1] == '*') && dp[0][j - 2]; for (int j = 1; j <= p.size(); ++j) for (int i = 1; i <= s.size(); ++i) { if (p[j - 1] != '*') //如果不是*,只有p遍历到.或者p[j-1]和s[i-1]相等的时候匹配 dp[i][j] = dp[i - 1][j - 1] && (p[j - 1] == '.' || s[i - 1] == p[j - 1]); else dp[i][j] = dp[i][j - 2] ||//x*表示0个x的情况 (dp[i - 1][j - 2] && (p[j - 2] == '.' || p[j - 2] == s[i - 1])) ||//x*表示1个x的情况 //x*表示多个x的时候表示,此时必须s[0~i-2]与p[0~j-1]匹配且…… (dp[i - 1][j] && (p[j - 2] == '.' || p[j - 2] == s[i - 1])); } return dp[s.size()][p.size()]; }