1 题目
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
2 思路
使用动态规划的方法, 开辟一个大小是(s_size + 1) * (p_size + 1)的二维数组Match, Match[i][j]代表着s的前i个字符和p的前j个字符是否匹配, 要获取Match[i][j]的值首先要观察s的第i个字符(s[i - 1])和p的第j个字符(p[j - 1])的关系.
如果s[i - 1] = p[j - 1]或者是p[j - 1]为' . ', 那么s的前i个字符和p的前j个字符是否匹配取决于s的前i - 1个字符和p的前j - 1个字符是否匹配.
如果不满足上述条件, 但是p[j - 1]为' * ', 那么就需要观察' * '前面的字符(p[j - 2])和s的第i个字符的关系:
- 如果s[i - 1] = p[j - 2]或者是p[j - 2]为' . ', 也就是说, 假设匹配上的字符是a(p[j - 2] = a), 那么如果此时我们可以用任意个数的a加在p的前j-2个字符的后面看是否匹配, 那么此时我们不用一个一个枚举我们加了多少个a, 只需要枚举加了一个a还是不加a, 因为加了一个a的话就是看s的前i-1个字符跟p的前j-2个字符是否匹配, 它可以重复这个过程, 最终遍历所有情况, 不加a的话就是看s的前i个字符跟p的前j-2个字符是否匹配, 以上两种情况只要有一种满足匹配上就能保证s的前i个字符和p的前j个字符匹配得上, 所以可以进行抑或运算.
- 如果p[j - 1]为' * ', 但是不满足上面的s[i - 1] = p[j - 2]或者是p[j - 2]为' . ', 那么*前面的字符就一个都不能用了, 只能用0个, 也就是说此时就只能看s的前i个字符跟p的前j-2个字符是否匹配.
所以代码如下:
bool isMatch(string s, string p) {int s_size = s.size();int p_size = p.size();vector<vector<int> > Match;for (int i = 0; i <= s_size; i ++) {vector<int> tmp;tmp.resize(p_size + 1);Match.push_back(tmp);}Match[0][0] = 1;for (int i = 0; i <= s_size; i ++) {for (int j = 1; j <= p_size; j ++) {if (i == 0) {//当i是0的时候,也就是说此时s一个字符也没有,如果此时p有字符, 那么每个字符后面//必须有*,代表着这些字符都是0个的时候才能匹配上,否则就匹配不上.Match[i][j] = p[j - 1] == '*' ? Match[i][j - 2] : 0;} else {if (s[i - 1] == p[j - 1] || p[j - 1] == '.') {Match[i][j] = Match[i - 1][j - 1];} else if (p[j - 1] == '*') {if (s[i - 1] == p[j - 2] || p[j - 2] == '.') {Match[i][j] = Match[i - 1][j] | Match[i][j - 2];} else {Match[i][j] = Match[i][j - 2];}}}}}return Match[s_size][p_size];
}