题意:正则表达式。’.’代表任意字符,’*’代表前一个字符出现任意次。
例如:a*b 匹配ab,aab,aaab,aaaab……
解法一:DFS
1.p.length() == 0
2.p.length() == 1
3.p.charAt(1) != '*'
4.p.charAt(1) == '*'
package edu.jnu;
public class Main {
public static void main(String[] args) {
// write your code here
Main m = new Main();
System.out.println(m.isMatch("aaba","ab*a*c*a"));
}
public boolean isMatch(String s, String p) {
//p.length() == 0
if (p.isEmpty())
return s.isEmpty();
if (p.length() == 1 || p.charAt(1) != '*') {
//根据德摩根定律,非(P 或 Q) = (非 P) 且 (非 Q)
if (s.length() < 1 || (p.charAt(0) != '.' && p.charAt(0) != s.charAt(0)))
return false;
return isMatch(s.substring(1), p.substring(1));
}
else{
//从-1开始是因为有 * 匹配 0 个的情况。
int i = -1;
while(i < s.length() && (i < 0 || p.charAt(0) == '.' || p.charAt(0) == s.charAt(i)))
if(isMatch(s.substring(++i),p.substring(2)))
return true;
return false;
}
}
}
解法二:DP
设dp[i][j] 表示s串当中以第i个字符结尾的子串,是否与p串当中以第j个字符结尾的子串相匹配,匹配值为1,否则为0。
初始化
1.空字符串s 匹配 空字符串p
2.空字符串p 不能与非空字符串s匹配
3.空字符串s,则下列情况与字符串p匹配
动态转移方程
这里主要针对‘*’进行讨论:
1.p[j] != '*'
如果s[i] == p[j] 或者 p[j] == '.'
dp[i][j] = dp[i-1][j-1];
下图中蓝色箭头。
2.p[j] == ‘*’
(1)如果‘*’前面的字符x与s串中的字符匹配大于等于一个,并且s[i] == p[j-1] 或者 p[j-1] == '.' ;
dp[i][j] = dp[i-1][j];
下图中绿色箭头。
(2)如果‘*’前面的字符x与s串中的字符匹配的个数为零。
dp[i][j] = dp[i][j-2];
下图中红色箭头。
Sample:
对应上面Sample的dp数组:
public boolean isMatch(String s, String p) {
int sLength = s.length(),pLength = p.length();
boolean[][] dp = new boolean[sLength+1][pLength+1];
//空s串 匹配 空p串
dp[0][0] = true;
//空p串 不能匹配 非空s串
for(int i = 1;i <= sLength;i++)
dp[i][0] = false;
//只有形式如:a*b*c*…… 的字符串可以匹配空s
for(int j = 1;j <= pLength;j++){
if(j > 1 && p.charAt(j-1) == '*')
dp[0][j] = dp[0][j-2];
}
for(int i = 1;i <= sLength;i++){
for(int j = 1;j <= pLength;j++){
if(p.charAt(j-1) != '*')
dp[i][j] = dp[i-1][j-1] && (s.charAt(i-1) == p.charAt(j-1) || p.charAt(j-1) == '.');
else
dp[i][j] = dp[i][j-2] || (s.charAt(i-1) == p.charAt(j-2) || p.charAt(j-2) == '.') && dp[i-1][j];
}
}
return dp[sLength][pLength];
}