Leetcode_10_Regular Expression Matching

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];        
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值