困难题
思路:遍历正则表达式,查找正则表达式的前 i 项能匹配 字符串的前多少项(可能有很多种匹配方式),这样的话,对于每一个 i 我们都能得到一个列表,并且每一个 i 对应的列表是通过 i - 1 对应的列表得到的。递推到最后,如果列表中含有字符串的最后一项则返回true。总体是一个动态规划的思想。
4ms 24%
class Solution {
public boolean isMatch(String s, String p) {
if(p.length() == 0)
return s.length() == 0 ? true : false;
int index = 0;
List<Integer> l = new ArrayList<>();
l.add(0);
while(index < p.length()){
List<Integer> t = new ArrayList<>();
if(p.charAt(index) == '.'){
if(index + 1 < p.length() && p.charAt(index + 1) == '*'){
index ++;
for(Integer j:l)
for(int i = j; i <= s.length(); i++)
t.add(i);
}
else{
for(Integer i:l)
t.add(i + 1);
}
}else{
if(index + 1 < p.length() && p.charAt(index + 1) == '*'){
index ++;
for(Integer i:l){
t.add(i);
int j = i;
while(j < s.length() && s.charAt(j) == p.charAt(index - 1)){
t.add(j + 1);
j++;
}
}
}
else {
int num = 0;
for(Integer i:l){
if(i < s.length() && s.charAt(i) == p.charAt(index)){
t.add(i + 1);
}
else
num ++;
}
if(num == l.size())
return false;
}
}
index ++;
Set<Integer> set = new HashSet<>(t);
t = new ArrayList<>(set);
l.clear();
l.addAll(t);
}
if(l.contains(s.length()))
return true;
else
return false;
}
}
更好的动规思想:定义二维数组 dp[i][j] 代表正则表达式的前 i 项 是否能与字符串的前 j 项相匹配。因为是对于每一个 i 遍历 j,所以就是对于 字符串的前 i 项 查找正则表达式的前 j 项能否匹配后再查找 i+1项,那么对于如果在 i + 1 时 第 j 项是 ’ * ',并且i + 1 与 j - 1项匹配,我们想要知道 ’ * '到底重复用了多少次,只需判断dp[i][j] 即可。还是看代码吧,
1ms 100%
class Solution {
public boolean isMatch(String s, String p) {
int m = s.length();
int n = p.length();
boolean[][] f = new boolean[m + 1][n + 1];
// s 与 p 都为空时,为 true
f[0][0] = true;
for (int i = 0; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (p.charAt(j - 1) == '*') {
// 如果第 j 项为 *
f[i][j] = f[i][j - 2];
if (matches(s, p, i, j - 1)) {
// 若 s 的第 i 项,匹配 p 的 第 j-1 项
// 那么 f[i][j] = *一个都没有匹配(f[i][j - 2]),s递归往前匹配(f[i - 1][j])
f[i][j] = f[i][j] || f[i - 1][j];
}
} else {
// 如果不为 *,直接看是否匹配就行
if (matches(s, p, i, j)) {
f[i][j] = f[i - 1][j - 1];
}
}
}
}
return f[m][n];
}
public boolean matches(String s, String p, int i, int j) {
if (i == 0) {
return false;
}
if (p.charAt(j - 1) == '.') {
return true;
}
return s.charAt(i - 1) == p.charAt(j - 1);
}
}