NC44 通配符匹配
题意分析:
给定字符串S,模式串P,判断S是否能够被P所匹配,通配符只有?和*,?可以匹配任意一个字符,*可以匹配任意长度的字符串
题解一(动态规划):
设置表示字符串S的(0-i)部分是否被字符串P的(0-j)部分匹配
初始化:
,字符串s的(0-0)为空,那么只要字符串P的(0-j)的部分开始为*就为true
,模式串(0-0)为空,根本没发匹配,
状态转移
- 如果P[j]=="*",并且
==true,或者
==true,那么
- 如果p[j]!="*",分两种情况
- 当p[j]=="?"时候,s[i]任意,并且
==true时候,
- 当p[j]==s[i]并且
==true时候,
- 当p[j]=="?"时候,s[i]任意,并且
- 如果P[j]=="*",并且
举个例子:
当模式串p为空,s不匹配p,所以第一行均为F,下图红色部分
当匹配串为空。除非p以*开头,不然均为false,所以第一行红色部分为false
接下来我们按行更新:从下图的第三行开始更新
更新第三行:
- 当s_start = a,p_start = a时候,我们要检查他的对角处是不是T,为T则为T,否则则为false
- 当s_start = d,p_start = a时候,s_start和p_start均为字母,我们要检查交叉处的左边即可。字母虽然不等,当交叉处左边为T就为T
- 同理第一行的其他部分
更新第四行
- 当s_start=a,p_start=*时候,由于*可以匹配0个或多个字符,因此我们只要检查交叉处上方是否为T即可
- 第四行其他位置同
更新第六行
- 当p_start=?,s_start = a,由于?可以匹配a,那么就需要检查交叉处的左边是否为T,作为为F那么就为F。其他位置的更新同上。
写成代码:
bool isMatch(const char *s, const char *p) {
int m = strlen(s);
int n = strlen(p);
vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
dp[0][0] = true;
for (int i = 1; i <= n; i++) {
if (p[i - 1] == '*') {
//初始化第一列
dp[0][i] = dp[0][i - 1];
}
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
//按照当前字符是否为*,
if (p[j - 1] == '*' && (dp[i - 1][j] || dp[i][j - 1])) {
dp[i][j] = true;
} else {//不为*的情况
if (p[j - 1] == '?' && dp[i - 1][j - 1]) {
//当为?
dp[i][j] = true;
} else if (p[j - 1] == s[i - 1] && dp[i - 1][j - 1]) {
//当两个字符相等的时候
dp[i][j] = true;
}
}
}
}
return dp[m][n];
} 时间复杂度:,mn分别为模式串P和匹配串S的长度。
空间复杂度:。
题解二(贪心):
模式串中的一个?刚好可以匹配一个字符,容易处理。对于,它可以匹配任意长度的字符串,当遇到\时,可以选择忽略,或者选择匹配一定长度的字符串。我们遇到*去做贪心选择,每一次只会产生一个结果,因此,如果某次贪心错误,应该回溯到另外一个位置,然后再进行贪心选择。
我们设置两个全局变量i_start和j_start表示s和p中匹配*,初始化为-1.
变量i和j表示当前匹配的位置
- 如果s和p的字符发生匹配,即s[i]==s[j]或者p[j] =='?',那么i++,j++
- 如果当前p[j]=="*",这将i_start和j_start分别设置为i和j,j++
- 如果i_start>=0,说明有被匹配过,\可以匹配任意长度的字符串,那么就一直增加i,j跳到j_start。
- 当匹配结束,如果指针j没有移动到匹配串末尾,那么在p可以匹配S的情况下,p中剩余没匹配的一定是*,否则无法完全匹配。
bool isMatch(const char *s, const char *p) {
int i = 0, j = 0, i_Star = -1, j_Star = -1;
int m = strlen(s), n = strlen(p);
while (i < m) {
if (j < n && (s[i] == p[j] || p[j] == '?')) {
i++;
j++;
} else if (j < n && p[j] == '*') {
i_Star = i;
j_Star = j;
j++;
} else if (i_Star >= 0) {
i_Star++;
i = i_Star;
j = j_Star;
} else {
return false;
}
}
while (j < n && p[j] == '*') {
j++;
}
return j == n;
} 时间复杂度:
空间复杂度:

京公网安备 11010502036488号