正则表达式匹配
题目:正则表达式匹配
思路
-
状态表示:选第一个字符串的
[0, i]
区间和第二个字符串的[0, j]
区间作为研究对象
dp[i][j]
表示字符串s1
中[1, i]
区间和字符串s2
中[1, j]
区间是否可以匹配 -
状态转移方程:根据
s1
和s2
的最后一个位置,进行讨论p[j]
在a - z
时,p[j] == s[i] && dp[i - 1][j - 1] == true --- > true
p[j] == '.'
时,dp[i - 1][j - 1] == true --- > true
p[j] == '*'
时,再细分p[j - 1] == '.'
,对其“翻译”- 空串,
dp[i][j - 2]
- 一个点,
dp[i - 1][j - 2]
- 两个点,
dp[i - 2][j - 2]
... ... ...
;上述有一个true
,就是true
优化:
p[j - 1] == '.'
- 我们注意到
dp[i][j] = dp[i][j - 2] || dp[i - 1][j - 2] || dp[i -2][j -2] || ... ...
dp[i - 1][j] = dp[i - 1][j -2] || dp[i - 2][j - 2] || dp[i -3][j -2] || ... ...
- 所以,
dp[i][j] = dp[i][j - 2] || dp[i - 1][j]
- 空串,
p[j - 1]
在a - z
时,对其“翻译”- 空串,
dp[i][j - 2]
- 匹配一个,然后保留,
p[j - 1] == s[i] && dp[i - 1][j]
- 空串,
综上,状态转移方程为:
dp[i][j]
p[j]
能匹配时,即s[i] == p[j] || p[j] = '.'
,此时看看&& dp[i - 1][j -1]
dp[i][j -2] || (p[j -1] == ',' || p[j -1] == s[i]) && dp[i -1][j]
-
初始化:引入空串,注意下标映射
- 初始化整个数组为
false
dp[0][0]
表示两个,初始化为true
- 第一列表示
p
为空串,不可能匹配上s
串; - 第一行表示
s
为空串,偶数位置连续为*
才为true
否则跳出;
- 初始化整个数组为
-
填表顺序:从上往下,从左往右
-
返回值:
dp[m][n]
C++代码
class Solution
{
public:
bool isMatch(string s, string p)
{
int m = s.size(), n = p.size();
s = " " + s, p = " " + p;
vector<vector<bool>> dp(m + 1, vector<bool>(n + 1));
dp[0][0] = true;
for (int i = 2; i <= n; i += 2)
if (p[i] == '*')
dp[0][i] = true;
else
break;
for (int i = 1; i <= m; ++i)
for (int j = 1;