最近项目中需要用到正则表达式对文件名进行匹配。在上传文件时,如果文件名中含有连续的相同字母或数字,则不允许上传。并且文件名中必须含有设备型号。
正则表达式描述了字符串的匹配模型。
- +:表示前面的字符必须出现至少一次(1次或多次)
eg:runoo+b可以匹配runoob、runooob、runoooob - :表示前面的字符可以不出现,也可以出现一次或多次(0次,1次或多次)
eg:runoo\b可以匹配runob、runoob、runooob - ?:表示前面的字符出现0次或1次。
eg:do(es)?可以匹配”do”或”does”
eg:colou?r 可以匹配 color 或者 colour
正则表达式匹配
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。
链接:https://leetcode-cn.com/problems/regular-expression-matching
【分析】
需要明确一点:s=a,p=ca,返回为true。因此`c是放在一起看的,
c*`表示有0个c,或者多个c。
s:真实的字符串
p:带有正则表达式的字符串
看p是否能匹配s
定义dp状态
dp[i][j]表示s的前i个字符[0,i)是否能匹配p的前j个字符[0,j)。这里是左闭右开,也就是dp[i][j]比较的是s[i-1]和p[j-1],有2种关系
- s[i-1]==p[j-1]
- s[i-1]!=p[j-1]
- p[j-1]是a~z的一个字母
- p[j-1]是
*
- p[j-1]是
.
下面分别考虑以上情况
s[i-1]==p[j-1]
dp[i][j]=dp[i-1][j-1]s[i-1]!=p[j-1] 且p[j-1]=
*
*
表示前面的字符是0个或多个。*
前面的字符为p[j-2],看是否和s[i-1]相等- p[j-2]==s[i-1]或p[j-2]=
.
*
表示p[j-2]可以是0个或多个
(1) 当*
取0个时,例如s=aab
,b=aabb*
,虽然s[i-1]==p[j-2],但由于dp[i][j-2]已经匹配了,所以此时的dp[j-2]是多余的,所以*
取0。此时dp[i][j]=dp[i][j-2]
(2) 当*
取1个字符时, 例如s=aab
,b=aab*
,dp[i][j]=dp[i][j-1]
(3) 当*
取多个字符时,例如s=aabb
,b=aab*
,dp[i][j]=dp[i-1][j]
- p[j-2]==s[i-1]或p[j-2]=
- s[i-1]!=p[j-1] 且p[j-1]=
.
.
是万能字符,可以把.
变成s[i-1]的字符,dp[i][j]=dp[i-1][j-2]
- s[i-1]!=p[j-1] 且p[j-1]是普通字符
那s的前i个字符和p的前j个字符就不匹配了,dp[i][j]=False
初始化dp
- dp[0][0]=True
- dp[0][j]:表示s的前0个字符和p的前j个字符匹配情况,如果p[j-1]是
*
,则可以把p[j-1]和p[j-2]的字符删去,只有dp[0][j-2]为true,才能让dp[0][j]为trueif p[j-1]=='*' and dp[0][j-2]
-