算法练习5


算法练习5

Regular Expression Matching

Implement regular expression matching with support for '.' and '*'.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'.' Matches any single character.
'*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") ? false
isMatch("aa","aa") ? true
isMatch("aaa","aa") ? false
isMatch("aa", "a*") ? true
isMatch("aa", ".*") ? true
isMatch("ab", ".*") ? true
isMatch("aab", "c*a*b") ? true

解题思路

题目大意:实现正则式中的'.''*' 匹配。

该问题可以具有最优子结构,所以可以用动态规划来求解。

首先分析这个问题,我们把这个问题可以看成是重复的比较字符串s的某个字符和字符串p的某个字符。在这个比较过程中有三种情况:

1
2
3
4
5
1, p.charAt(j) == s.charAt(i)//s当前字符相等
2, p.charAt(j) == '.'//s当前字符与通配符'.'匹配
3, p.charAt(j) == '*'//这种情况还需要细分两种情况
3.1, p.charAt(j-1) != s.charAt(i)//s当前字符与'*'前一字符不相等
3.2, p.charAt(i-1) == s.charAt(i) or p.charAt(i-1) == '.'//'*'前一字符与之相等或前一字符是通配符

基于以上情况,定义dp[i][j]为s串前i个字符与p串前j个字符的匹配状态。那么我们可以得到每种情况对应的状态转移方程:

1
2
3
4
5
6
1, if p.charAt(j) == s.charAt(i) : dp[i][j] = dp[i-1][j-1];
2, if p.charAt(j) == '.' : dp[i][j] = dp[i-1][j-1];
3, if p.charAt(j) == '*' :
if p.charAt(j-1) != s.charAt(i) : dp[i][j] = dp[i][j-2];
if p.charAt(i-1) == s.charAt(i) || p.charAt(i-1) == '.' :
dp[i][j] = dp[i-1][j] || dp[i][j] = dp[i][j-1] || dp[i][j] = dp[i][j-2];

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Solution {
public boolean isMatch(String s, String p) {
if (s == null || p == null) return false;
boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];
dp[0][0] = true;
for (int i = 0; i < p.length(); i++) {
if (p.charAt(i) == '*' && dp[0][i - 1]) {
dp[0][i + 1] = true;
}
}
for (int i = 0; i < s.length(); i++) {
for (int j = 0; j < p.length(); j++) {
if (p.charAt(j) == s.charAt(i)) {
dp[i+1][j+1] = dp[i][j];
}
if (p.charAt(j) == '.') {
dp[i+1][j+1] = dp[i][j];
}
if (p.charAt(j) == '*') {
if (p.charAt(j -1) != s.charAt(i) && p.charAt(j - 1) != '.') {
dp[i + 1][j + 1] = dp[i + 1][j - 1];
} else {
dp[i+1][j+1] = (dp[i+1][j] || dp[i][j+1] || dp[i+1][j-1]);
}
}
}
}

return dp[s.length()][p.length()];
}
}

文章作者: Amos Liu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Amos Liu !
 上一篇
算法练习6 算法练习6
算法练习6Maximum SubarrayFind the contiguous subarray within an array (containing at least one number) which has the largest
2017-06-10
下一篇 
粗读ArrayList 粗读ArrayList
粗读ArrayList概览ArrayList大概是除了String用了最多的类了。ArrayList对数组进行封装,实现了List接口。下面是ArrayList的私有变量: 123456789101112131415161718192021
2017-05-20
  目录