LeetCode 10.正则表达式匹配
双序列型动态规划
确定状态:
设A
长度为m
,B
的长度为n
- 如果
B[n-1]
是一个正常字符(非.
非*
),则如果A[m-1]=B[n-1]
,能否匹配
取决于A[0..m-2]
和B[0..n-2]
是否匹配;否则不能匹配 - 如果
B[n-1]
是.
,则A[m-1]
一定是和.
匹配,之后能否匹配取决于A[0..m-2]
和B[0..n-2]
是否匹配 - 如果
B[n-1]
是*
,它代表B[n-2]=c
可以重复0次或多次,它们是一个整体c*
,
需要考虑A[m-1]
是0个c
,还是多个c
中的最后一个
–A[m-1]
是0个c
,能否匹配取决于A[0..m-1]
和B[0..n-3]
是否匹配
–A[m-1]
是多个c
中的最后一个,能否匹配取决于A[0..m-2]
和B[0..n-1]
是否匹配,这种情况必须A[m-1]=c
或者c=‘.’
- 状态:设
f[i][j]
为A
前i
个字符A[0..i-1]
和B
前j
个字符B[0..j-1]
能否匹配
转移方程:
初始条件和边界情况:
- 空串和空正则表达式匹配:
f[0][0] = true
- 空的正则表达式不能匹配长度
>0
的串f[1][0] = … = f[m][0] = false
- 注意:
f[0][1..n]
也用动态规划计算,但是因为没有A[-1]
,所以只能用第二种情况中的f[i][j-2]
class Solution {
public boolean isMatch(String s, String p) {
char[] s1=s.toCharArray();
char[] s2=p.toCharArray();
int m=s1.length;
int n=s2.length;
boolean[][] f=new boolean[m+1][n+1];
int i,j,k;
f[0][0]=true;
for(i = 0;i <= m;i++){
for(j = 0;j <= n;j++){
if(i == 0 && j == 0){
f[i][j] = true;
continue;
}
if(j == 0){
f[i][j] = false;
continue;
}
f[i][j] = false;
if(s2[j-1] != '*'){
if(i > 0 && (s2[j-1] == '.' || s1[i-1] == s2[j-1]))
f[i][j] = f[i-1][j-1];
}
else{
if(j > 1){
f[i][j] |= f[i][j-2];
}
if(i > 0 && j > 1){
if(s2[j-2] == '.' || s1[i-1] == s2[j-2]){
f[i][j] |= f[i-1][j];
}
}
}
}
}
return f[m][n];
}
}