动态规划之正则表达式匹配
1. 题目描述
原字符串
s
s
s (只含字母)与字符规律
r
r
r (可含 字母
⋅
\cdot
⋅ 及
∗
*
∗),检验两者是否匹配,匹配规则为:
1)
⋅
\cdot
⋅ 匹配任意单个字符
2)
∗
*
∗ 匹配零个或多个前面的那一个元素
注意:有一种组合极为特殊,可构成万物,即 "
⋅
∗
\cdot\ *
⋅ ∗ ",实际上
∗
*
∗为前一个字符的拷贝,如果该字符为
⋅
\cdot
⋅ ,意味这
⋅
∗
\cdot\ *
⋅ ∗等于
n
n
n个
⋅
\cdot
⋅,
n
n
n可以为0。
2. 思路与算法
定义:
v
v
v :字符匹配的状态转移矩阵
v
[
i
]
[
j
]
v[i][j]
v[i][j] :
s
s
s 的前
i
i
i 个字符与 pp 中的前
j
j
j 个字符的匹配情况
状态转移分析:
考虑
r
r
r 的第
j
j
j 个字符的匹配情况与**
s
s
s** 的第
i
i
i 个字符:
- 如果两者均为字母, 如果
s
[
i
]
s[i]
s[i]与
r
[
j
]
r[j]
r[j]匹配,则
v
[
i
]
[
j
]
v[i][j]
v[i][j]只取决于
v
[
i
−
1
]
[
j
−
1
]
v[i-1][j-1]
v[i−1][j−1],否则显然不匹配:
1)当 s [ i ] = r [ j ] s[i]=r[j] s[i]=r[j]时, v [ i ] [ j ] v[i][j] v[i][j]= v [ i − 1 ] [ j − 1 ] v[i-1][j-1] v[i−1][j−1];
2)当 s [ i ] ≠ r [ j ] s[i]≠ r[j] s[i]=r[j]时, v [ i ] [ j ] v[i][j] v[i][j]=0; - 如果
r
[
j
]
=
⋅
r[j]=\cdot
r[j]=⋅,意味着
s
[
i
]
s[i]
s[i]与
r
[
j
]
r[j]
r[j]匹配,则
v
[
i
]
[
j
]
v[i][j]
v[i][j]只取决于
v
[
i
−
1
]
[
j
−
1
]
v[i-1][j-1]
v[i−1][j−1]:
1) v [ i ] [ j ] v[i][j] v[i][j]= v [ i − 1 ] [ j − 1 ] v[i-1][j-1] v[i−1][j−1]; - 如果
r
[
j
]
=
∗
r[j]=*
r[j]=∗, 由于
∗
*
∗为前一个字符的拷贝,说明要想验证
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] ,需要验证
s
[
i
]
s[i]
s[i]与
r
[
j
−
1
]
r[j-1]
r[j−1]之间的关系,设
r
[
j
−
1
]
=
α
r[j-1]=\alpha
r[j−1]=α, 则
r
[
j
−
1
]
r
[
j
]
=
α
∗
r[j-1]r[j]=\alpha\ *
r[j−1]r[j]=α ∗:
1)当 α ≠ ⋅ \alpha≠\cdot α=⋅时," α ∗ \alpha\ * α ∗ "可以认为不存在,则不必考究 s [ i ] s[i] s[i]与 r [ j − 1 ] r[j-1] r[j−1]之间的关系,探索 s [ i ] s[i] s[i]与 r [ j − 2 ] r[j-2] r[j−2]的关系即可,必然满足 v [ i ] [ j ] v[i][j] v[i][j]= v [ i ] [ j − 2 ] v[i][j-2] v[i][j−2];
2) 当 α = ⋅ \alpha=\cdot α=⋅时, " ⋅ ∗ \cdot\ * ⋅ ∗ “可以匹配任意字符,” ⋅ ∗ \cdot\ * ⋅ ∗ " 不在乎其对应的是什么字符,哪怕你再多加一个字符又如何,必然满足 v [ i ] [ j ] v[i][j] v[i][j]= v [ i − 1 ] [ j ] v[i-1][j] v[i−1][j] 。
综上所述,状态转移方程如下:
3. 代码
class Solution {
public:
bool isMatch(string s, string p) {
int s_size=s.size(), p_size=p.size();
vector<vector<int>> v2(s_size+1, vector<int>(p_size+1));
v2[0][0]=1;
for(int i=0;i<=s_size;i++){
for(int j=1;j<=p_size;j++){
if(p[j-1]=='*'){
v2[i][j]=v2[i][j-2];
if(ismatch(s, p ,i, j-1)){
v2[i][j] |= v2[i-1][j];
}
}
else{
if(ismatch(s, p ,i, j)) v2[i][j]|=v2[i-1][j-1];
}
}
}
return v2[s_size][p_size];
}
bool ismatch(string& s, string& p, int i, int j){
if(i==0) return false;
if(p[j-1]=='.') return true;
return s[i-1]==p[j-1];
}
};