2018年4月8日,这个题写了一整天,主要是题意理解都是坑啊。。。。。。
题目翻译:
实现支持 “.” 和 “*”的正则表达式匹配。
“.”匹配任何单个字符。
“*”匹配零个或多个上一个元素。
匹配应该覆盖整个输入字符串(不是部分)。
题目这里有个坑,就是对“*”的理解,“a*”是一个整体,它可以代表”null”(“”) ”a” ”aa” ”aaa”……
初看题,觉得是最长公共子序列类型(讲解:https://blog.csdn.net/have_a_cat/article/details/79815487)
分析:
设 Sn= <s1,s2,…,sn> , Pm = <p1,p2,…,pm>
f[i,j] =true 表示 Si 与 Pj匹配
那么:
(1) 如果 si = pj ,则f[i,j]=f[i-1,j-1]
(2) 如果“.” = pj ,则 f[i,j]=f[i-1,j-1]
(3) 如果“*” = pj
----<1>si =pj-1 , f[i,j]=f[i-1,j] || f[i,j-1] || f[i-1,j-2]
----<2>“.” =pj-1 , f[i,j]= f[i-1,j] || f[i,j-1] || f[i-1,j-2] (很容易忽略的情况)
----<3>除了<1>和<2>的其他情况,f[i][j]=f[i][j-2];
对上面的分析分别举例:
情况(1):
S2= <a,b> ;P3=<a,c,b>; i=2, j =3;
s2== p3, f[2,3]=f[2-1,3-1]=f[1,2]
情况(2):
S2= <a,b> ;P2=<a,.>;i=2, j =2;
“.” == p2,f[2,2]=f[2-1,2-1]=f[1,1]
情况(3) <1>:
S2= <a,a> ;P2=<a,*>;i=2, j =2;
“*” == p2, s2=a=p1 f[2,2]=f[2-1,2]=f[1,2] // a*在这里不仅代表“a”,代表”a…”
S2= <a,a > ;P3=<a,a,*>;i=2, j =3;// a*在这里代表“a”
“*” == p3, s2=a=p2 f[2,3]=f[2,3-1]=f[2,2]
S1 =<a> ; P3=<a,a, *>;i=1, j =3;
“*” == p3, s1=a=p2 f[1,3]=f[1,3-2]=f[1,1] //不对a*进行匹配
以上三种情况下,综合得f[i,j]= f[i-1,j]||f[i,j-1]||f[i-1,j-2]
情况(3) <2>:
S2= <a,a> ;P2=<.,*>;i=2, j =2;
“*” == p2, “.”=p1 f[2,2]=f[2-1,2]=f[1,2] // .*在这里不仅代表“a”,代表”a…”
S2= <a,a > ;P3=<a, .,*>;i=2, j =3;
“*” == p3, “.”=p2 f[2,3]=f[2,3-1]=f[2,2] //.*在这里代表“a”
S1 =<a> ; P3=<a, ., *>;i=1, j =3;
“*” == p3, “.”=p2 f[1,3]=f[1,3-2]=f[1,1] //不对.*进行匹配
以上三种情况下,综合得f[i,j]= f[i-1,j]||f[i,j-1]||f[i-1,j-2]
情况(3) <3>:
S3= <a,a,a> ;P7=< ab*ac*a >;i=2, j =6;
“*” == p6, s2!=p5, “.”!=p5, f[2,6]=f[2,6-2]=f[2,4]//不对c*进行匹配
初始化:
(1) f[0][0]=true;S0 = <>, P0 = <>, S0 与 P0 匹配
(2)
for (int i = 2; i < (m+1); i++)
{
if (p.charAt(i-1) == '*' &&f[0][i-2])
{
f[0][i] = true;
}
}
解释:
S4= <a,a,b,c> 与P4 = < a,a,b,c > 匹配
S4= <a,a,b,c> 与P6 = < c,*,a,a,b,c> 匹配
S4= <a,a,b,c> 与P8 = < d,*,c,*,a,a,b,c> 匹配
S4= <a,a,b,c> 与P10 = < c,*,d,*,c,*,a,a,b,c> 匹配
… …
JAVA代码:
class Solution {
public boolean isMatch(String s, String p) {
//初看题,觉得是最长公共子序列类型
if (s == null || p == null) {
return false;
}
int n = s.length();//s的长度 s为标准
int m = p.length();
boolean[][] f = new boolean[n+1][m+1];
for(int i1=0;i1<(n+1);i1++)
{
Arrays.fill(f[i1],false);
}
//初始化
f[0][0]=true;
for (int i = 2; i < (m+1); i++)
{
if (p.charAt(i-1) == '*' && f[0][i-2])
{
f[0][i] = true;
}
}
//
for(int i=1;i<(n+1);i++)
{
for(int j=1;j<(m+1);j++)
{
//分情况讨论 (1)s=char p=char
// (2) p=.
// (3) p=*
if(s.charAt(i-1)==p.charAt(j-1))//(1)
{
f[i][j] = f[i-1][j-1];
}
if(p.charAt(j-1)=='.')//(2)
{
f[i][j] = f[i-1][j-1];
}
if(p.charAt(j-1)=='*')//(3)-此题最难理解部分
//[a*] 代表0个或多个a,可能为'null' 'a' 'aa' 'aaa' ...
{
//1>-s(i)==p(j-1) f[i-1][j]
//2>-p(j-1)=='.' f[i-1][j-1]
//3>-s(i)!=p(j-1) f[i][j-2]
if((s.charAt(i-1)==p.charAt(j-2))||(p.charAt(j-2)=='.'))
{
f[i][j]=(f[i-1][j]||f[i][j-1]||f[i][j-2]);
}
else
{
f[i][j]=f[i][j-2];
}
}
//System.out.println("["+i+","+j+"]="+s.charAt(i-1)+"-"+p.charAt(j-1)+"->"+f[i][j]);
}
}
return f[n][m];
}
}