编程之美---正则匹配

19 篇文章 0 订阅
17 篇文章 0 订阅

动态规划,关键是处理 * 号, 根据匹配次数进行 状态转移,关键点是 多次匹配时, 保留星号,待匹配字符串划掉当前匹配字符,通过递归,即为多次匹配,不需要手动去写一个循环来处理 多次匹配。仅仅 匹配一次时, 星号去掉,待匹配字符串划掉当前匹配字符。

class Solution {
public:
	int width;

	bool isMatch(const char * s, const char *p, int * mem, const char * s_src, const char *p_src)
	{
		if (*s == '\0' && *p == '\0')
		{
			int rows = (s - s_src);
			int cols = (p - p_src);

			mem[rows * width + cols] = 1;

			return true;
		}

		if (*p == '\0' && *s != '\0')
		{
			int rows = (s - s_src);
			int cols = (p - p_src);

			mem[rows * width + cols] = 0;

			return false;
		}

		int rows = (s - s_src);
		int cols = (p - p_src);
		if (mem[rows * width + cols] != -1)
		{
			return mem[rows * width + cols];
		}

		if (*p != '\0' && *(p + 1) == '*')
		{
			// 后面是*, 那么尝试匹配
			auto res = isMatch(s, p + 1, mem, s_src, p_src);
			if (res)
			{
				int rows = (s - s_src);
				int cols = (p+1 - p_src);

				mem[rows * width + cols] = 1;

				return res;
			}
			else
			{
				int rows = (s - s_src);
				int cols = (p + 1 - p_src);

				mem[rows * width + cols] = 0;

				return false;
			}
		} else if (*p != '*')
		{
			if (*s != '\0' && (*s == *p || *p == '.'))
			{
				auto res = isMatch(s + 1, p + 1, mem, s_src, p_src);

				int rows = (s + 1 - s_src);
				int cols = (p + 1 - p_src);

				mem[rows * width + cols] = res;

				return res;
			}
			else
			{
				int rows = (s - s_src);
				int cols = (p - p_src);

				mem[rows * width + cols] = 0;

				return false;
			}
		}
		else
		{
			// 先匹配0次, 0次不需要和前面的字符进行比较
			auto res = isMatch(s, p + 1, mem, s_src, p_src);
			if (res)
			{
				int rows = (s - s_src);
				int cols = (p+1 - p_src);

				mem[rows * width + cols] = 1;
				return true;
			}
			else
			{
				// 尝试匹配 1次或者 多次, 此时需要和前面的字符一致
				// 至少 匹配一次的话, s 不能已经到末尾
				if ((*s != '\0') &&  (*s == *(p - 1) || *(p - 1) == '.'))
				{
					// 尝试匹配多次
					auto res = isMatch(s + 1, p, mem, s_src, p_src);
					if (res)
					{
						int rows = (s+1 - s_src);
						int cols = (p - p_src);

						mem[rows * width + cols] = 1;
						return true;
					}
					else
					{
						// 尝试只匹配一次,跳过这个*,看后续是否能匹配成功
						auto res = isMatch(s + 1, p + 1, mem, s_src, p_src);
						if (res)
						{
							int rows = (s+1 - s_src);
							int cols = (p+1 - p_src);

							mem[rows * width + cols] = 1;
							return true;
						}
						else
						{
							int rows = (s+1 - s_src);
							int cols = (p+1 - p_src);

							mem[rows * width + cols] = 0;
							return false;
						}
					}
				}
				else
				{
					int rows = (s - s_src);
					int cols = (p - p_src);

					mem[rows * width + cols] = 0;
					return false;
				}
			}
		}
	}

	bool isMatch(string s, string p) {

		int rows = s.length() + 1;
		int cols = p.length() + 1;

		int * mem = new int[rows * cols];
		memset(mem, 0xff, rows * cols * sizeof(int));

		width = p.length();

		const char * s_src = s.c_str();
		const char * p_src = p.c_str();

		return isMatch(s_src, p_src, mem, s_src, p_src);
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值