Wildcard Matching的几种解法与思路

通配符匹配问题

给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。

  • ‘?’ 可以匹配任何单个字符
  • ‘*’ 可以匹配任意字符串(包括空字符串)

两个字符串完全匹配才算匹配成功。

说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。

思路1:动态规划

这个题其实有点像==“编辑距离”==(编辑距离算法详解)的问题,可以根据两个字符串的长度mn(m=s.size();n=p.size()),划分成一个(n+1)(m+1)的编辑矩阵record,也是看最后矩阵record[n][m]的值。

对于字符串s=“bcd"与p=”?ec"

初始化矩阵如下:

在这里插入图片描述

然后遍历矩阵

有以下三种情况

  1. 如果s[i]p[j] or p[j]’?’ 那么record[i+1][j+1]=record[i][j]

  2. 如果p[j]’’ 那么record[i+1][j+1]=record[i][j+1] || record[i+1][j]

  3. s[i] != p[j] 那么record[i+1][j+1]=0;

最后矩阵长这样:

在这里插入图片描述

然后矩阵最后一项record[n][m]=0 所以不匹配

然后这次我们考虑通配符’‘

首先要考虑 ‘’ 在字符串首的情况,

’’ 可以匹配所有字符串,所以需要将record[1][0]置为1,根据上述情况2,可以将这一行都置为1

如果首个字符为’‘且后面还接有’’,那么record[i][0]均为1

考虑下面矩阵:s=“bcd” p="**cd"

在这里插入图片描述

然后我们按照上面的规则,初始化矩阵

在这里插入图片描述

然后遍历矩阵,重复3种情况的判定,得到结果

在这里插入图片描述

代码如下:

class Solution {
public:
	bool isMatch(string s, string p) {
		int i = 0, j = 0, n = s.size(), m = p.size();
		bool **record = new bool[m + 1];
		for (int u = 0; u < m + 1; u++)
		{
			record[u] = new bool[n + 1];
                        memset(record[u], 0, sizeof(bool)(n+1));//设置初值为0
		}
		record[0][0] = true;
		for (int i = 1; i <= m; i++)//初始化矩阵,对于存在’'为字符串首的情况
			record[i][0] = record[i - 1][0] && p[i - 1] == '’;
		for (j = 0; j<m; j++)
		{
			for (i = 0; i < n; i++)//3种情况判定
			{
				if (s[i] == p[j] || p[j] == ‘?’)
				{
					record[j + 1][i + 1] = record[j][i];
				}
				else if (p[j] == ‘*’)
				{
					record[j + 1][i + 1] = record[j][i + 1] || record[j + 1][i];
				}
				else
				{
					record[j + 1][i + 1] = 0;
				}
			}
		}
		return record[m][n];
	}
};

思路2:双指针

从上面可以看出,如果是两个巨长的字符串,也许两个字符串从第一个字符比较就可以判定不匹配了,但是通过动态规划的方法我们进行了很多多余的计算,所以这里引入双指针的方法,对每个字符串引入一个指针进行比较判断。

· 引入2个指针 i , j 分别指向两个字符串的串首

· 引入2个指针ri , rj 分别记录字符串指针i , j 的状态

· 当 i 指向串尾 且 j 指向串尾时 返回 true,其余情况 false

同样判断4种情况

  1. p[j]’?’ || s[i]p[j] 那么 i++; j++

  2. p[j] ‘’ 那么 ri = i ; rj = j; j++;

  3. rj > -1 那么 i = ++ri; j = rj +1;

  4. 其余情况 return false;

到最后可能 j 并没有指向串尾,而是指向 '’,跳过冗余的’’ 如果 j 指向串尾那么return true 否则 return false;

对于 s=“bcd” p="**cd" 相当于只进行了 以下箭头的计算,所以更加便捷

在这里插入图片描述

对于 s=“bbb” p="**cd" :
在这里插入图片描述

class Solution {
public:
	bool isMatch(string s, string p) {
		int n = s.size(), m = p.size();
		int i = 0, j = 0, ri = -1, rj = -1;
		while (i < n)
		{
			if (p[j] == '’)
			{
				ri = i;
				rj = j++;
			}
			else if (p[j] == ‘?’ || p[j] == s[i])
			{
				i++; j++;
			}
			else if (rj > -1)
			{
				i = ++ri;
				j = rj+1;
			}
			else return false;
		}
		while (j < m&&p[j] == ‘’)j++;
		return j == m;
	}
};

思路3:递归

整体思路与上面双指针类似,只不过是通过递归的方式完成,runtime比思路1快比思路2慢。

class Solution {
		 int dfs(string& s, string& p, int si, int pi) {
			 if (si == s.size() and pi == p.size()) return 2;
			 if (si == s.size() and p[pi] != '’) return 0;
			 if (pi == p.size()) return 1;
			 if (p[pi] == ‘’) {
				 if (pi + 1 < p.size() and p[pi + 1] == '’)
					 return dfs(s, p, si, pi + 1); // skip duplicate ‘*’
				 for (int i = 0; i <= s.size() - si; ++i) {
					 int ret = dfs(s, p, si + i, pi + 1);
					 if (ret == 0 or ret == 2) return ret;
				 }
			 }
			 if (p[pi] == ‘?’ or s[si] == p[pi])
				 return dfs(s, p, si + 1, pi + 1);
			 return 1;
		 }
 
	 public:
		 bool isMatch(string s, string p) {
			 return dfs(s, p, 0, 0) > 1;
		 }
};
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在SV语言中,case语句用于根据不同的条件执行不同的代码块。它类似于其他编程语言中的switch语句。case语句可以使用wildcard来匹配多个条件。通常使用通配符"*"来表示任意值。当case语句的条件与通配符匹配时,相应的代码块将被执行。这在编写测试用例时非常有用,可以覆盖多种情况。使用wildcard可以简化代码并提高可读性。例如,下面是一个使用wildcard的case语句的示例: ```systemverilog case (signal) 4'b10?? // 当signal的值为10开头的任意两位数时执行此代码块 4'b01?? // 当signal的值为01开头的任意两位数时执行此代码块 default // 当signal的值与上述条件都不匹配时执行此代码块 endcase ``` 在上述示例中,当signal的值为10开头的任意两位数时,第一个代码块将被执行;当signal的值为01开头的任意两位数时,第二个代码块将被执行;当signal的值与上述条件都不匹配时,default代码块将被执行。使用wildcard可以方便地处理多种情况,提高代码的灵活性和可维护性。\[2\] #### 引用[.reference_title] - *1* *2* *3* [【数字设计验证】System Verilog(sv)稍微进阶的笔记(一)](https://blog.csdn.net/qq_43658753/article/details/128505261)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值