请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。
这道题目感觉比较难。一遇到字符串问题就害怕。结合何老师的课本讲解,以及网上的其他资料进行了相应的学习。下面是相关总结。
首先,给定两个字符串,分别是匹配字符串s与模式串p。匹配字符串是全英文字母的,模式串具有一些特殊字符 '.','*'、根据两个特殊字符的效果,可以将匹配问题分成两类,'*'与非'*'类型。
首先当前字符为非*时,直接将s[i]与p[j]比较即可。具体表示为s[i]==p[j]||p[j]=='.'这时,两字符串是始终匹配的。
若当前字符为*时,则需要分类讨论。因为*可以表示出现0次的情况,这时候,只需要判别s[i+1]与p[j+2]的情况.当出现次数不为0时,需要判断s[i+1]与p[j]的关系。
这里参考了大佬的动态规划的思想,设定状态表示矩阵f[i][j],代表s[i...end],p[j...end]是匹配的情况。
状态转移方程表示为:
1.如果p[j+1]!=*;f[i][j]为真,当且仅当s[i]可以和p[j]匹配,且f[i+1][j+1]是真
2.如果p[j+1]=*;则下面情况中只要有一种满足,f[i][j]就是真
f[i][j+2]是真
s[i+1]与p[j]匹配,且f[i+1][j]是真。
import java.util.*;
public class Solution {
public boolean match(char[] str, char[] pattern) {
int n=str.length;
int m=pattern.length;
int f[][]=new int[n+1][m+1];
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
f[i][j]=-1;
}
}
return dp(0,0,f,str,pattern);
}
public boolean dp(int x,int y,int f[][],char[]str,char[]pattern) {
if(f[x][y]!=-1) return f[x][y]>0;
int n=str.length;
int m=pattern.length;
if(y==m){
if(x==n){
f[x][y]=1;
}
return f[x][y]>0;
}
boolean first_match=x<n&&(str[x]==pattern[y]||pattern[y]=='.');
boolean ans;
if(y+1<m&&pattern[y+1]=='*'){
ans=dp(x,y+2,f,str,pattern)||(first_match&&dp(x+1,y,f,str,pattern));
}else{
ans=first_match&&dp(x+1,y+1,f,str,pattern);
}
if(ans){
f[x][y]=1;
}
return f[x][y]>0;
}
}
记录一下,这道题肯定是要2刷3刷的。