题意:
给定一个串s,再给定一个正则表达式 p 问 p能不能生成s
样例中较难理解的的是
isMatch("ab", ".*") → true
这可以等价于 ab和 .. 这样就好理解了。
思路:动态规划
先将p做下预处理,变成两个数组,第一个数组是字符,第二个数组标记对应的字符是否可以出现多次。然后dp[i][j] 表示到s串到 i的位置,p串到j 是否能匹配。有3种转移
一: dp[i-1][j-1]为true 且i和j对应的字符相等
二: dp[i-1][j]为true 且i和j对应字符相等,且j那个字符可以出现多次
三: dp[i][j-1]为true 且j对应的字符可以出现多次(这边取出现0次)
上述3种有一种成立则 dp[i][j]=true
代码如下:
class Solution {
public:
bool isMatch(string s, string p) {
int slen=s.length();
int plen=0;
int num[p.length()+2];
string a="";
for(int i=0;i<p.length();++i){
if(p[i]=='*')
num[plen-1]=-1;
else{
num[plen++]=1;
a+=p[i];
}
}
p=a;
bool ok[slen+2][plen+2];
memset(ok,0,sizeof(ok));
ok[0][0]=true;
for(int j=1;j<=plen;++j){//初始化,注意前面连续为0 的情况,也可以 下面写法写成后推 的形式就可以不用这一步 ,而我用的是前推
if(num[j-1]==-1){
ok[0][j]=true;
}else
break;
}
for(int i=1;i<=slen;++i){
for(int j=1;j<=plen;++j){
if(ok[i-1][j-1]){//转移1
if(s[i-1]==p[j-1]||p[j-1]=='.'){
ok[i][j]=true;
}
}
if(ok[i-1][j]){//转移2
if((s[i-1]==p[j-1]||p[j-1]=='.')&&num[j-1]==-1){
ok[i][j]=true;
}
}
if(ok[i][j-1]){//转移3
if(num[j-1]==-1){
ok[i][j]=true;
}
}
}
}
return ok[slen][plen];
}
};