剑指offer_ 正则表达式匹配

请实现一个函数用来匹配包括 '.' 和 '*' 的正则表达式。模式中的字符 '.' 表示任意一个字符,而 '*' 表示它前面的字符 可以出现任意次(包含 0 次)。

当模式中的第二个字符不是“*”时:

1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。
2、如果 字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。

而当模式中的第二个字符是“*”时:
如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式:
1、模式后移2字符,相当于x*被忽略;
2、字符串后移1字符,模式后移2字符;
3、字符串后移1字符,模式不变,即继续匹配字符下一位,因为*可以匹配多位;

这里需要注意的是:Java里,要时刻检验数组是否越界。
 1 public class Solution {
 2 
 3 
 4  public boolean match(char[] str, char[] pattern) {
 5     if (str == null || pattern == null) {
 6         return false;
 7     }
 8     int strIndex = 0;
 9     int patternIndex = 0;
10     return matchCore(str, strIndex, pattern, patternIndex);
11 }
12   
13 public boolean matchCore(char[] str, int strIndex, char[] pattern, int patternIndex) {
14     //有效性检验:str到尾,pattern到尾,匹配成功
15     if (strIndex == str.length && patternIndex == pattern.length) {
16         return true;
17     }
18     //pattern先到尾,匹配失败
19     if (strIndex != str.length && patternIndex == pattern.length) {
20         return false;
21     }
22     //模式第2个是*,且字符串第1个跟模式第1个匹配,分3种匹配模式;如不匹配,模式后移2位
23     if (patternIndex + 1 < pattern.length && pattern[patternIndex + 1] == '*') {
24         if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) {
25             return matchCore(str, strIndex, pattern, patternIndex + 2)//模式后移2,视为x*匹配0个字符
26                   //  || matchCore(str, strIndex + 1, pattern, patternIndex + 2)//视为模式匹配1个字符
27                     || matchCore(str, strIndex + 1, pattern, patternIndex);//*匹配1个,再匹配str中的下一个
28         } else {
29             return matchCore(str, strIndex, pattern, patternIndex + 2);
30         }
31     }
32     //模式第2个不是*,且字符串第1个跟模式第1个匹配,则都后移1位,否则直接返回false
33     if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) {
34         return matchCore(str, strIndex + 1, pattern, patternIndex + 1);
35     }
36     return false;
37     }
38 }

先前是使用拷贝数组各种越界错误

另外还有一个方法

 1 public class Solution {
 2 
 3 
 4  public boolean match(char[] str, char[] pattern) {
 5              int m = str.length, n = pattern.length;
 6              boolean[][] dp = new boolean[m + 1][n + 1];
 7              dp[0][0] = true;
 8              for (int i = 1; i <= n; i++)
 9              if (pattern[i - 1] == '*')
10              dp[0][i] = dp[0][i - 2];
11              for (int i = 1; i <= m; i++)
12              for (int j = 1; j <= n; j++)
13              if (str[i - 1] == pattern[j - 1] || pattern[j - 1] == '.')
14              dp[i][j] = dp[i - 1][j - 1];
15              else if (pattern[j - 1] == '*')
16              if (pattern[j - 2] == str[i - 1] || pattern[j - 2] == '.') {
17              dp[i][j] |= dp[i][j - 1]; // a* counts as single a
18              dp[i][j] |= dp[i - 1][j]; // a* counts as multiple a
19              dp[i][j] |= dp[i][j - 2]; // a* counts as empty
20              } else
21              dp[i][j] = dp[i][j - 2]; // a* only counts as empty
22              
23              return dp[m][n];
24             }
25 }

 dp[i][j]表示str前i个与pattern的前j个是否匹配

posted @ 2019-08-24 11:27  chyblogs  阅读(142)  评论(0)    收藏  举报