Skip to content

2019-06-08 2019-06-09每日一题 #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions daily/2019-06-09.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
## 每日一题 - Regular Expression Matching

### 信息卡片

- 时间:2019-06-09
- 题目链接:https://leetcode.com/problems/regular-expression-matching/
- tag:`String` `Dynamic Programming` `Backtracking`

### 题目描述

```
Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.


'.' Matches any single character.
'*' Matches zero or more of the preceding element.


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

Note:


s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters
like . or *.


Example 1:


Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".


Example 2:


Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*' means zero or more of the precedeng element, 'a'.
Therefore, by repeating 'a' once, it becomes "aa".


Example 3:


Input:
s = "ab"
p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".


Example 4:


Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore
it matches "aab".


Example 5:


Input:
s = "mississippi"
p = "mis*is*p*."
Output: false

```

本题要求判断给出的字符串和对应的正则是否匹配,匹配返回true,否则返回false。

本题光从解题来看,可以使用api作弊,比如用Java字符串的matches方法就可以一步过这道题,本题老老实实做的话,就需要用到动态规划。基本思路是考察s和p任意从头到两个字符之间的匹配程度,有点像编辑距离那道题。

### 参考答案

```java
class Solution {
public boolean isMatch(String s, String p) {
if (s == null || p == null) return false;

// dp[i][j]代表s的前i位字符和p的前j位字符的匹配程度
// dp[1][2]代表s的第一个字符和p的前两个字符的匹配
// 如果s的第i个字符和p的第j个相等或者j为.那么di[i][j]的匹配程度取决于dp[i - 1][j - 1]
// 如果p的第j个字符为*,那么就要考虑*匹配0个,1个,n个s的第i个字符的情况,以及根本匹配不了的情况
// 根本匹配不了的意思是指p的j - 1个字符和s的第i个字符不相同,此时的匹配情况是dp[i][j] = dp[i][j - 2]
// 然后是p的第j - 1个字符是.或者和s的i个字符相同的情况,此时可以匹配0 1 个n个s的第i个字符
// 0个: dp[i][j] = dp[i][j - 2]
// 1个: dp[i][j] = dp[i - 1][j - 1]
// n个: dp[i][j] = dp[i - 1][j]
// n个的最不好理解,可以按照下面的想
// 我能匹配你n个,我肯定匹配了你前面的n-1个,也就是dp[i - 1][j]
// 最后的结果是dp[s.length()][p.length()]
boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];

dp[0][0] = true;

for (int j = 2; j <= p.length(); j++) {
if (p.charAt(j - 1) == '*' && dp[0][j - 2]) dp[0][j] = true;
}

for (int i = 1; i <= s.length(); i++) {
for (int j = 1; j <= p.length(); j++) {
if (p.charAt(j - 1) == '.' || p.charAt(j - 1) == s.charAt(i - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else if (p.charAt(j - 1) == '*') {
if (p.charAt(j - 2) != s.charAt(i - 1) && p.charAt(j - 2) != '.') {
dp[i][j] = dp[i][j - 2];
} else {
dp[i][j] = (dp[i][j - 2] || dp[i][j - 1] || dp[i - 1][j]);
}
}
}
}

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

```
### 其他优秀解答
```
暂无
```
8 changes: 7 additions & 1 deletion daily/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,16 @@ tag: `Array`

#### [347.Top K Frequent Elements](./2019-06-08.md)

tag: `HashTable Heap`
tag: `HashTable` `Heap`

时间: 2019-06-08

#### [10.Regular Expression Matching](./2019-06-09.md)

tag: `String` `Dynamic Programming` `Backtracking`

时间: 2019-06-09

#### [617. Merge Two Binary Trees](./2019-06-10.md)

tag: `Tree`
Expand Down