正则表达式匹配
问题描述:请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
示例
输入:"aaa","a*a"
返回值:true
方法一
思路分析
首先对题目进行分析,首先将两个字符串转换为字符串数组str,pattern,则进行如下的分析:
- 如果两个字符串均为空字符串,则直接返回true
- 如果原先的字符串不为空,待匹配的字符串是空的则直接返回false
- 字符串数组pattern开始位置的下一位置为'*',如果两个字符串开始位置比较,这里匹配存在两种情况,即str字符串是否为空
- ----如果str字符串为空,则pattern向后移动两个字符,继续比较match(str,pattern[2:])
- ----否则如果str字符串不为空则存在三种可能的情况:
- -----接着如果str[0]=pattern[0]或者pattern[i]=‘.’,例如str=aaa,pattern=.*aa,那么pattern数组中'*'前面字符可以出现任意次,如果出现0次,那么继续匹配match(str,pattern[2:]);如果出现1次,匹配match(str[1:],pattern[2:]),如果出现大于1次,匹配match(str[1:],pattern)
- 字符串数组pattern开始位置的下一位置不为'*',且两个字符串的开始位置相同或者patter的开始字符为'.',则直接继续比较后面的字符串match(str[1:],pattern[1:])
python核心代码
# # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # # @param str string字符串 # @param pattern string字符串 # @return bool布尔型 # class Solution: def match(self , str , pattern ): # write code here if len(str) == 0 and len(pattern) == 0: return True if len(str) > 0 and len(pattern) == 0:#原字符串不为空,待匹配的字符串为空,直接返回false return False if len(pattern) > 1 and pattern[1] == '*': if len(str) > 0 and (str[0] == pattern[0]&nbs***bsp;pattern[0] == '.'):#两个字符相同或者待匹配的字符为.可匹配成功 return self.match(str, pattern[2:])&nbs***bsp;self.match(str[1:], pattern[2:])&nbs***bsp;self.match(str[1:], pattern) else: return self.match(str, pattern[2:]) if len(str) > 0 and (pattern[0] == '.'&nbs***bsp;pattern[0] == str[0]): return self.match(str[1:], pattern[1:]) return False
复杂度分析
- 时间复杂度:程序不断的递归,因此时间复杂度为$O(n^2)$
- 空间复杂度:空间复杂度为$O(1)$
方法二
思路分析
本题也可使用动态规划的办法,设置二维数组dp[str.length][pattern.length]记录某一位置上的字符是否匹配,即采用顺序遍历的办法,顺序遍历两个字符串,当前位置的两个字符是否匹配的,匹配的状态取决于上一状态的值,具体步骤如下:
- 待匹配的字符串数组上一位置pattern[j-1]为'*',如果str[i-1]== pattern[j-2 ]或者pattern[j-2] == '.',那么pattern数组中'*'前面字符可以出现任意次,则其状态转移方程为$dp[i][j] = dp[i][j - 2] || dp[i - 1][j]$;否则模式的'*'前一位字符与字符串的上个字符不匹配,那么状态转移方程为$dp[i][j]=dp[i-][j-2]$
- 如果模式的前一位字符与字符串的上个字符匹配,即str[i-1]== pattern[j-1 ]或者pattern[j-1] == '.',状态转移方程$dp[i][j]=dp[i-1][j-1]$
图解
JAVA核心代码
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param str string字符串 * @param pattern string字符串 * @return bool布尔型 */ public boolean match (String str, String pattern) { // write code here if (str == null || pattern == null) { return false; } boolean[][] dp = new boolean[str.length() + 1][pattern.length() + 1]; dp[0][0] = true; int n1=str.length(); int n2=pattern.length(); for (int i = 0; i <= n1; i++) { for (int j = 1; j <= n2; j++) { if (j > 1 && pattern.charAt(j-1) == '*') { if (i > 0 && (str.charAt(i-1) == pattern.charAt(j-2) || pattern.charAt(j-2) == '.')) { //模式的'*'前一位字符与字符串的上个字符匹配 dp[i][j] = dp[i][j - 2] || dp[i - 1][j]; } else { //模式的'*'前一位字符与字符串的上个字符不匹配 dp[i][j] = dp[i][j - 2]; } } else if (i > 0 && (str.charAt(i - 1) == pattern.charAt(j-1) || pattern.charAt(j-1) == '.')) { //模式的前一位字符与字符串的上个字符匹配 dp[i][j] = dp[i - 1][j - 1]; } } } return dp[n1][n2]; } }
复杂度分析
- 时间复杂度:内外两层循环遍历,时间复杂度为$O(str.length*pattern.length)$
- 空间复杂度:借助于一个二位辅助数组,空间复杂度为$O(str.length*pattern.length)$