package jianzhioffer; public class test19 { public static void main(String[] args) { } /** * 如果 BB 的最后一个字符是正常字符,那就是看 A[n-1]A[n−1] 是否等于 B[m-1]B[m−1],相等则看 A_{0..n-2}A 0..n−2 与 B_{0..m-2}B 0..m−2 ,不等则是不能匹配,这就是子问题。 如果 BB 的最后一个字符是.,它能匹配任意字符,直接看 A_{0..n-2}A 0..n−2 与 B_{0..m-2}B 0..m−2 如果 BB 的最后一个字符是*它代表 B[m-2]=cB[m−2]=c 可以重复0次或多次,它们是一个整体 c*c∗ 情况一:A[n-1]A[n−1] 是 00 个 cc,BB 最后两个字符废了,能否匹配取决于 A_{0..n-1}A 0..n−1 和 B_{0..m-3}B 0..m−3 是否匹配 情况二:A[n-1]A[n−1] 是多个 cc 中的最后一个(这种情况必须 A[n-1]=cA[n−1]=c 或者 c='.'c= ′ . ′ ),所以 AA 匹配完往前挪一个,BB 继续匹配,因为可以匹配多个,继续看 A_{0..n-2}A 0..n−2 和 B_{0..m-1}B 0..m−1 是否匹配。 转移方程 f[i] [j]f[i][j] 代表 AA 的前 ii 个和 BB 的前 jj 个能否匹配 对于前面两个情况,可以合并成一种情况 f[i][j] = f[i-1][j-1]f[i][j]=f[i−1][j−1] 对于第三种情况,对于 c*c∗ 分为看和不看两种情况 不看:直接砍掉正则串的后面两个, f[i][j] = f[i][j-2]f[i][j]=f[i][j−2] 看:正则串不动,主串前移一个,f[i][j] = f[i-1][j]f[i][j]=f[i−1][j] 初始条件 特判:需要考虑空串空正则 空串和空正则是匹配的,f[0][0] = truef[0][0]=true 空串和非空正则,不能直接定义 truetrue 和 falsefalse,必须要计算出来。(比如A=A= '' '' ,B=a*b*c*B=a∗b∗c∗) 非空串和空正则必不匹配,f[1][0]=...=f[n][0]=falsef[1][0]=...=f[n][0]=false 非空串和非空正则,那肯定是需要计算的了。 * @param s * @param p * @return */ public boolean isMatch(String s, String p) { int n=s.length(); int m=p.length(); boolean [][]f=new boolean[n+1][m+1]; for(int i=0;i<=n;i++){ for(int j=0;j<=m;j++){ if(j==0){ f[i][j]=(i==0); }else{ if(p.charAt(j-1)!='*'){ if(i>0&&(s.charAt(i-1)==p.charAt(j-1)||p.charAt(j-1)=='.')){ f[i][j]=f[i-1][j-1]; } }else{ if(j>=2){ f[i][j]|=f[i][j-2]; } if(i>=1&&j>=2&&(s.charAt(i-1)==p.charAt(j-2)||(p.charAt(j-2)=='.'))){ f[i][j]|=f[i-1][j]; } } } } } return f[n][m]; } }