方法一:动态规划
创建一个bool类型数组dp,大小为(str.length() + 1)* (pattern.length() + 1),用来存储str到pattern是否匹配;
dp[i][j] 表示str[i - 1]和pattern[j - 1]是否匹配,可以得到如下的状态转移方程:
如果str[i - 1] == pattern[j - 1]或者pattern[j - 1] =='.'(可替代任何字符,等同于相等),dp[i][j] = dp[i - 1][j - 1];
如果不相等时,只要当pattern[j - 1]为‘*’时,才有可能匹配,可以分三种情况讨论:
(1)重复0次:dp[i][j] = dp[i][j - 2];
(2)重复1次:dp[i][j] = dp[i][j - 1];
(3)重复多次:dp[i][j] = dp[i - 1][j];
时间复杂度:o(mn)
空间复杂度:o(mn)
class Solution { public: bool match(string str, string pattern) { vector<vector<bool> > dp(str.length() + 1, vector<bool>(pattern.length() + 1, false)); // 边界设置 dp[0][0] = true; for (int i = 1; i <= pattern.length(); i++) { if (pattern[i - 1] == '*') dp[0][i] = dp[0][i - 2]; } for (int i = 1; i <= str.length(); i++) { for (int j = 1; j <= pattern.length(); j++) { if (str[i - 1] == pattern[j - 1] || pattern[j - 1] == '.') { dp[i][j] = dp[i - 1][j - 1]; } else if (pattern[j - 1] == '*') { // 重复0次 if (dp[i][j - 2] && j >= 2) dp[i][j] = dp[i][j - 2]; // 重复1次 else if (dp[i][j - 1] && j >= 1) dp[i][j] = dp[i][j - 1]; // 重复多次 else if ((str[i - 1] == pattern[j - 2] || pattern[j - 2] == '.') && j >= 2 && i >= 1) { dp[i][j] = dp[i - 1][j]; } } } } return dp[str.length()][pattern.length()]; } };
方法二:递归
此方法复杂度较高,会导致超时。
class Solution { public: bool match(string str, string pattern) { return matchCore(str, pattern); } bool matchCore(string str, string pattern) { if (str.empty() && pattern.empty()) return true; if (!str.empty() && pattern.empty()) return false; if (pattern[1] == '*') { if (pattern[0] == str[0] || (pattern[0] == '.' && !str.empty())) // 重复0次 return matchCore(str, pattern.substr(2)) || // 重复一次 matchCore(str.substr(1), pattern.substr(2)) || // 重复多次 matchCore(str.substr(1), pattern); else return matchCore(str, pattern.substr(2)); } if (str[0] == pattern[0] || (pattern[0] == '.' && !str.empty())) return matchCore(str.substr(1), pattern.substr(1)); return false; } };