请实现一个函数用来匹配包含‘. ‘和‘*‘的正则表达式。模式中的字符‘.‘表示任意一个字符,而‘*‘表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但与"aa.a"和"ab*a"均不匹配。
示例 1:
输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:
s = "aa"
p = "a*"
输出: true
解释: 因为 ‘*‘ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a‘。因此,字符串 "aa" 可被视为 ‘a‘ 重复了一次。
示例 3:
输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个(‘*‘)任意字符(‘.‘)。
示例 4:
输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 ‘*‘ 表示零个或多个,这里 ‘c‘ 为 0 个, ‘a‘ 被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入:
s = "mississippi"
p = "mis*is*p*."
输出: false
s 可能为空,且只包含从 a-z 的小写字母。p 可能为空,且只包含从 a-z 的小写字母以及字符 . 和 *,无连续的 ‘*‘。采用
动态规划的思想:
1.定义状态:dp[i][j]表示主串s的前i个字符和正则串p的前j个字符是否匹配
2.初始化dp数组:因为状态转移是从小到大,后面的状态需要依靠前面的状态判断。即需要初始化dp数组的首行和首列
dp[0][0]表示s和p都是空串,很明显dp[0][0]=true- 首列
dp[i][0]=false(i!=0),因为主串s不为空,而正则串p为空,明显不匹配- 首行
dp[0][j]比较特殊,s为空的情况下,p的偶数位为‘*‘的话是可以匹配上的,因为可以让‘*‘之前的字符出现次数为03.状态转移方程:因为已经初始化了首行和首列,s和p都从索引1开始匹配。下面开始分情况讨论:
正则串p的第j个字符为
‘*‘,即p[j-1]==‘*‘
- 若
dp[i][j-2]为true,那么dp[i][j]也为true
即s的前i个字符和p的前j-2个字符匹配,且p的第j个字符为‘*‘,那么无论p的第j-1个字符是什么,令它出现0次,dp[i][j]就可以为true- 若
dp[i-1][j] && s[i-1]==p[j-2]条件为true,那么dp[i][j]也为true
即s的前i-1个字符和p的前j个字符匹配,且s的第i个字符和p的第j-1个字符相等,让p的第j-1个字符多出现一次,s的前i字符和p的前j的字符就可以匹配了- 若
dp[i-1][j] && p[j-2]=‘.‘条件为true时,那么dp[i][j]也为true
即s的前i-1个字符和p的前j个字符匹配,因为‘.‘字符可以匹配任意字符,那么s的第i个字符可以匹配p的第j-1个字符,令p的第j-1个字符多出现一次即可上述2,3可以合并为一个判断语句:
dp[i-1][j] && s[i-1]==p[j-2] || dp[i-1][j] && p[j-2]==‘.‘正则串p的第j个字符不为
‘*‘,即p[j-1]!=‘*‘
- 若
dp[i-1][j-1] && s[i-1]==p[j-1]条件为true,那么dp[i][j]也为true
即s的前i-1个字符和p的前j-1个字符匹配,且s的第i个字符和p的第j个字符也相同- 若
dp[i-1][j-1] && p[j-1]==‘.‘条件为true,那么dp[i][j]也为true
即s的前i-1个字符和p的前j-1个字符匹配,且p[j-1]=‘.‘,因为‘.‘可以匹配s[i]的任意字符串上述可以合并为一个判断语句:
dp[i-1][j-1] && s[i-1]==p[j-1] || dp[i-1][j-1] && p[j-1] == ‘.‘4.返回值:即
dp[n][m],主串的前n个字符和正则串的前m个字符是否匹配
func isMatch(s string, p string) bool {
//获取主串s和正则串p的长度
n, m := len(s), len(p)
//创建dp数组
dp := make([][]bool, n+1)
for i := 0; i < n+1; i++ {
dp[i] = make([]bool, m+1)
}
//初始化dp数组
dp[0][0] = true
//初始化首行 首列直接为false
for j := 2; j < m+1; j = j + 2 {
dp[0][j] = dp[0][j-2] && p[j-1] == ‘*‘
}
//索引从1开始,分情况讨论
for i := 1; i < n+1; i++ {
for j := 1; j < m+1; j++ {
//正则串p的第j个字符不为‘*‘,即p[j-1]!=‘*‘
if p[j-1] != ‘*‘ {
if dp[i-1][j-1] && s[i-1] == p[j-1] {
dp[i][j] = true
} else if dp[i-1][j-1] && s[i-1] == p[j-1] || dp[i-1][j-1] && p[j-1] == ‘.‘ {
dp[i][j] = true
}
} else { //正则串p的第j个字符为‘*‘,即p[j-1]==‘*‘
if dp[i][j-2] == true {
dp[i][j] = true
} else if dp[i-1][j] && s[i-1] == p[j-2] || dp[i-1][j] && p[j-2] == ‘.‘ {
dp[i][j] = true
}
}
}
}
return dp[n][m]
}
原文:https://www.cnblogs.com/zmk-c/p/14661850.html