poj和leetcode|44带通配符的字符串匹配

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

‘?’ 可以匹配任何单个字符。
‘*’ 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/wildcard-matching

不说了,本人就是菜,对着leetcode的反例反复修改。
简洁的大佬答案,请移步:大佬的代码
大佬代码思路是动态规划。
A[i][j]表示是a[i]和b[j]之前的字符串的匹配情况。真则匹配,假则不匹配。
A[i][j]的确定规则如下:

  • 当a[i]时?或者非*的其他字符的时候,就检查a[i]和b[j]还有A[i-1][j-1]
  • 当a[i]为*的时候,就需要检查A[i-1][j]和A[i-1][j-1]和A[i][j-1]当这三个有一个是1的时候,A[i][j]就是1。

按照类似的思路,可以有如下操作
例如:*a *b     adceb

图一
确定A[1][1]的元素内容需要检查a[1],a[1]是a,所以是非*的字符,接着检查A[0][0],可以得到
A[0][0]=1,还需要检查a[1]和b[1],而a[1]和b[1]一个是a一个是b所以并不相等。A[1][1]就可以确定为是0。同理第二行的所有元素都需要和a[1]进行比较,而都不相等,所以可以得到第二行后续全部填入0。

在这里插入图片描述

确定A[2][1]的元素需要首先看a[2],可以得到a[2]是*,所以要检查A[1][0],A[2][0],A[1][1]。其中A[2][0]是1,所以要填入1。后续的推导类似。
在这里插入图片描述
依次完成整个表格的填写。
在这里插入图片描述
输出对应的在后下角的值对应的matched或者not matched就可以了。

以上是整体思路。
如下代码是自己写的,相对不太好看。

for (int i = 1; i < length; i++) {
		for (int n = 1; n < lengthb; n++) {
			if (a[i]=='?') {
				ch[i][n] =ch[i-1][n-1];
			}
			if (a[i] == '*') {
				if (ch[i - 1][n - 1]  || ch[i][n - 1] ||ch[i-1][n]) {
					ch[i][n] = 1;
				}
				else {
					ch[i][n] = 0;
				}
			}
			if (a[i] != '?'&&a[i] != '*') {
				 ch[i][n] = ch[i - 1][n - 1]*check(a,b,i,n);
			}
		}
	}

其中check()如下:

int check(char a[20],char b[20],int i,int n) {
	if (a[i] == b[n]) {
		return 1;
	}
	return 0;
}

还有一些零碎的个人在实现的过程中的思路。
为了上述过程的顺利实现,需要对第一行和第一列进行初始化操作。
对第一行的初始化相对简单。

  • 当a[0]是*的时候,第一行是1。
  • 当a[0]是?或者和b[0]相当的时候,第一行只有A[0][0]是1,其余是0。

对第一列进行初始化相对困难一点。可以反向思考,什么时候a[i]需要开始写入0。

  • 当a[0]是和b[0]不同的字符的时候
  • 当出现过?,其他a[n]全是*,n小于i,并且a[i]是第二个其他字符的时候。
  • 当出现过和b[0]同字母,其他a[n]全是*,n小于i,并且a[i]是第二个其他字符的时候。
    代码块如下:(ps:修改了好久,主要是初始化问题。还是总体思路不太好的结果)
int flag=1;
if (a[0] == b[0] || a[0] == '?')flag = 0;//如果a[0]是b[0]或者?就更改flag后续只要有非*就填入0
	for (; curr < length; curr++) {
		if (a[curr] == '*') {
			ch[curr][0] = ch[curr - 1][0];
		}
		else {
			if (flag && (a[curr] == b[0] || a[curr] == '?')) {
				ch[curr][0] = ch[curr - 1][0];
				flag = 0;
			}
			else {
				ch[curr][0] = 0;
			}
		}
	}

总的代码:

#include<stdio.h>
#include<stdlib.h>
int countmuiple(int a, int b);
int countdivi(int a, int b);
int check(char a[20], char b[20], int i, int n);
int main()
{
	char a[20];
	char b[20];
	gets_s(a);
	gets_s(b);
	int length = strlen(a);
	int lengthb = strlen(b);
	int curr = 1;
	int flag=1;
	int ch[20][20] = { 0 };
	if (a[0] == '*' || a[0] == '?' || a[0] == b[0]) {
		ch[0][0] = 1; 
	}
	else { 
		ch[0][0] = 0; 
	}
	for (int i = 1; i < lengthb; i++) {
		if (a[0] == '*') {
			ch[0][i] = 1;
		}else{
			ch[0][i] = 0;
		}
	}
	if (a[0] == b[0] || a[0] == '?')flag = 0;
	for (; curr < length; curr++) {
		if (a[curr] == '*') {
			ch[curr][0] = ch[curr - 1][0];
		}
		else {
			if (flag && (a[curr] == b[0] || a[curr] == '?')) {
				ch[curr][0] = ch[curr - 1][0];
				flag = 0;
			}
			else {
				ch[curr][0] = 0;
			}
		}
	}
	for (int i = 1; i < length; i++) {
		for (int n = 1; n < lengthb; n++) {
			if (a[i]=='?') {
				ch[i][n] =ch[i-1][n-1];
			}
			if (a[i] == '*') {
				if (ch[i - 1][n - 1]  || ch[i][n - 1] ||ch[i-1][n]) {
					ch[i][n] = 1;
				}
				else {
					ch[i][n] = 0;
				}
			}
			if (a[i] != '?'&&a[i] != '*') {
				 ch[i][n] = ch[i - 1][n - 1]*check(a,b,i,n);
			}
		}
	}
	if ((length == 0 && lengthb == 0) || (lengthb == 0 && (a[0] == '*' ) && length == 1)) {
		printf("matched");
	}
	else {
		if (length > 0 && lengthb > 0 && ch[length - 1][lengthb - 1]) {
			printf("matched\n");
		}
		else {
			printf("not matched\n");
		}
	}
}
int check(char a[20],char b[20],int i,int n) {
	if (a[i] == b[n]) {
		return 1;
	}
	return 0;
}
int check(char a[20],char b[20],int i,int n) {
	if (a[i] == b[n]) {
		return 1;
	}
	return 0;
}
bool isMatch(char * s, char * p){
	int length = strlen(p);
	int lengthb = strlen(s);
	int curr = 1;
    int flag=1;
	int ch[1500][1500] = { 0 };
	if (p[0] == '*' || p[0] == '?' || p[0] == s[0]) {
		ch[0][0] = 1; 
	}
	else { 
		ch[0][0] = 0; 
	}
	for (int i = 1; i < lengthb; i++) {
		if (p[0] == '*') {
			ch[0][i] = 1;
		}else{
			ch[0][i] = 0;
		}
	}
    if (p[0] == s[0]||p[0]=='?'){flag = 0;}
	for (; curr < length; curr++) {
		if (p[curr] == '*') {
			ch[curr][0] = ch[curr - 1][0];
		}
		else {
			if (flag&&(p[curr]==s[0]||p[curr]=='?')) {
				ch[curr][0] = ch[curr - 1][0];
				flag = 0;
			}
			else {
				ch[curr][0] = 0;
			}
		}
	}
	for (int i = 1; i < length; i++) {
		for (int n = 1; n < lengthb; n++) {
			if (p[i]=='?') {
				ch[i][n] =ch[i-1][n-1];
			}
			if (p[i] == '*') {
				if (ch[i - 1][n - 1]  || ch[i][n - 1] ||ch[i-1][n]) {
					ch[i][n] = 1;
				}
				else {
					ch[i][n] = 0;
				}
			}
			if (p[i] != '?'&&p[i] != '*') {
				 ch[i][n] = ch[i - 1][n - 1]*check(p,s,i,n);
			}
		}
	}
	if ((length == 0 && lengthb == 0)||(lengthb==0&&(p[0]=='*')&&length==1)) {
		return true;
	}
	else {
		if (length > 0 && lengthb > 0 && ch[length - 1][lengthb - 1]) {
		return true;
		}
		else {
			return false;
		}
	}
}

最后附上提交结果:
leetcode提交记录
在这里插入图片描述
poj的提交记录
在这里插入图片描述
代码反思:初始化操作没有和后续的动态规划进行合并,代码不是很简洁,同时给调试带来了很大的麻烦,动归部分反而几乎没有更改。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值