There are two solutions, one is my own recursive solution, the efficiency is very low, the boundary conditions are difficult to clear, the code is very long, the second is DP solution, the recursive sub-problem is saved into an array, the code is very short.
1. Recursive Solution
The main idea is to decide how to match next according to the current regular expression. We can use the substrings of two strings to match. The trouble is that the same substrings may be solved many times, especially the corresponding strings of. * need to be solved in a loop. After writing this solution, I naturally know that it can be solved by DP recursion, but the marginal conditions are difficult to determine, we can.
struct match
{
bool isMatch;
char c;
int pos;
};
class Solution {
public:
vector<match> matchArray;
string reg;
bool Match(string s, int current){
for (int i = 0; i < s.length(); ++i)
{
if (current >= matchArray.size())
{
return false;
}
match m = matchArray[current];
if (m.c == '.' && m.isMatch == true)
{
if (current == matchArray.size() - 1)
{
return true;
}
else
{
while(matchArray[current].isMatch){
current++;
if (current >= matchArray.size())
{
return true;
}
}
char c = matchArray[current].c;
bool isMatch = matchArray[current].isMatch;
for (int j = i; j < s.length(); ++j)
{
if (Match(s.substr(j), current))
{
return true;
}
}
return false;
}
}
else if (m.c == '.')
{
current++;
}
else if (m.isMatch == true)
{
if (Match(s.substr(i), current + 1))
{
return true;
}
else if (s[i] != m.c)
{
return false;
}
while(s[i] == m.c){
i++;
if (Match(s.substr(i), current + 1))
{
return true;
}
}
return false;
}
else if (m.c != s[i])
{
return false;
}
else{
current++;
}
}
for (int i = current; i < matchArray.size(); ++i)
{
if (matchArray[i].isMatch == false)
{
return false;
}
}
return true;
}
bool isMatch(string s, string p) {
reg = p;
if (p.length() == 0 && s.length() == 0)
{
return true;
}
else if (p.length() == 0 /*|| s.length() == 0*/)
{
return false;
}
for (int i = 0; i < p.length(); ++i)
{
match m;
m.pos = i;
m.c = p[i];
if (i + 1 < p.length() && p[i+1] == '*')
{
m.isMatch = true;
i++;
}
else{
m.isMatch = false;
}
matchArray.push_back(m);
}
return Match(s, 0);
}
};
- DP solution
We can naturally record the solution of the sub-problem, and the code is fully annotated.
// Since it can be solved recursively, it should be possible to record the case of sub-nodes and do DP.
// What we choose i s whether the substring of p length j matches the substring of s length I.
class Solution {
public:
bool dp[100][100];
bool isMatch(string s, string p) {
dp[0][0]=true;
for (int i = 1; i <= s.length(); ++i)
{
dp[i][0]=false;
}
int len1 = s.length();
int len2 = p.length();
for (int i = 0; i <= len1; ++i)
{
// Notice that i=0 corresponds to the case where s i s an empty string
for (int j = 1; j <= len2; ++j)
{
// The same j=0 corresponds to p=0, and we have initialized it.
// i,j corresponds to a string
if (p[j-1] == '*')
{
if (p[j-2]=='.' || (i>0&&p[j-2]==s[i-1]))
{
// p_j-2 can match the end of s, so it only needs the same match as s whose length I s i-1.
// Mainly x* can match 0/1:
// 1 If p can match s, then px* must match sx
// 2 If p does not match s, then:
// 2.1 If you want px* to match sx, then x* does not match a single x:
// 2.1.1 x* matches empty, then p matches sx, which is dp[i][j-2]=true
// 2.1.2 x* matches x x x x, and if k-times matches are made, px* must also match sxxxx (k-1 x)
// dp[i-1][j]=true (i > 0 is also required)
// 2.2 There are only two matching cases. If there is no matching, we can take the opposite one, while dp[i][j-2] has already made corresponding records, just use them directly.
// And because * does not appear at the beginning of p, J >= 2
// Some misunderstandings may arise here, as long as it is clear that the length of p[j-2] corresponds to j-1, and that of dp[i][j-2] corresponds to j-2.
dp[i][j]=(i>0&&dp[i-1][j])||dp[i][j-2];
}
else{
// If you can't match the end, x* doesn't work. It matches 0 times, corresponding to 2.1.1.
dp[i][j]=dp[i][j-2];
}
}
else if (i>0 && (p[j-1]=='.' || p[j-1]==s[i-1]))
{
// Here, if p can match s, then p. can match sx. If p can not match s, then p. can not match SX either.
// px and sx are identical
dp[i][j]=dp[i-1][j-1];
}
else{
// In other cases, that is to say, pa does not match sb, so let's temporarily make it equal to false.
// This condition, when I was in yy, I always thought about the situation that p has. * as if I couldn't figure it out.
// In fact, it is very simple, p'.*a and sb are not matched, p'. * in fact discussed in the first step.
dp[i][j]=false;
}
}
}
return dp[len1][len2];
}
};