首页 > 其他分享 >Luogu P3167 [CQOI2014]通配符匹配

Luogu P3167 [CQOI2014]通配符匹配

时间:2023-06-10 22:24:34浏览次数:51  
标签:return P3167 Luogu 通配符 pos got CQOI2014 false spe

[CQOI2014]通配符匹配

题目描述

几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户。最常见的通配符有两个,一个是星号(”“'),可以匹配0个及以上的任意字符:另一个是问号(”?“),可以匹配恰好一个任意字符。现在需要你编写一个程序,对于给定的文件名列表和一个包含通配符的字符串,判断哪些文件可以被匹配。

输入格式

第一行是一个由小写字母和上述通配符组成的字符串。第二行包含一个整数n,表示文件个数。接下来n行,每行为一个仅包含小写字母字符串,表示文件名列表。

输出格式

输出n行,每行为”YES“或”NO“,表示对应文件能否被通配符匹配。

样例 #1

样例输入 #1

*aca?ctc
6
acaacatctc
acatctc
aacacatctc
aggggcaacacctc
aggggcaacatctc
aggggcaacctct

样例输出 #1

YES
YES
YES
YES
YES
NO

提示

对于1 00%的数据

·字符串长度不超过1 00000

· 1 <=n<=100

·通配符个数不超过10

蜜汁纯暴力,把我炸的妈妈都不认识,呜呜呜┭┮﹏┭┮

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

typedef unsigned long long ull;
ull base[5211314], pre1[5211314], pre2[5211314];
ull t, len1, len2;
char got[5211314], temp[5211314], ask[5211314];
ull spe[521][2], spenum;

bool Work(int got_pos, int ask_pos, int spe_pos) {
	//got_pos通配符字符串的位置
	//ask_pos询问字符串的位置
	//spe_pos第几个通配符 
	//记得判断最后一个字符是不是在最后一位 
	//记得判断最后一个通配符 
	int len;
	int gl = got_pos, gr, al, ar;
	ull gans, aans;
	if (got_pos > len1) return false; 
	if (ask_pos > len2) return false;
	//若超出范围 
	if (spe_pos == spenum + 1) {
		gl = got_pos, gr = len1;
		al = ask_pos, ar = len2;
		gans = pre1[gr] - pre1[gl - 1] * base[gr - gl + 1];
		aans = pre2[ar] - pre2[al - 1] * base[ar - al + 1];
		if (gans == aans) return true;
		else return false;
	} 
	if (spe[spe_pos][0] != 0) flag1 = false;
	else flag1 = true;
	if (spe[spe_pos + 1][0] != 0) flag2 = false;
	else flag2 = true; 
	gr = spe[spe_pos + 1][flag2] - 1;
	//gr 为got上对应匹配的右端点 注意判断spe_pos的值是否为spenum 
	len = ((spe[spe_pos + 1][flag2] - 1) - (spe[spe_pos][flag1] + 1)) + 1;
	//len 为两个通配符之间的字符个数
	if (spe_pos == spenum) len = 0;
	//特判最后一个通配符 
	for (int i = ask_pos; i <= len2 - len + 1; ++ i) {
		if (spe_pos == 0) {
			if (len == 0) {
				//如果字符串第一个就是通配符 
				//** 注意 ** 用不用管flag2??? 
				return Work(got_pos + 1, ask_pos, spe_pos + 1))
				//下一个函数的got_pos注意要加一 
			}
			else {
				//将两个字符串比较 
				al = i;
				ar = al + len - 1;//非通配符串的右节点 
				if (ar > len2) return false;
				//如果通配符子串的长度大于非通配符子串的长度 
				gans = pre1[gr] - pre1[gl - 1] * base[gr - gl + 1];
				aans = pre2[ar] - pre2[al - 1] * base[ar - al + 1];
				if (gans == aans) {
					return Work(spe[spe_pos + 1][falg2], ar + 1, spe_pos + 1);
					//这里下一个函数如果不能返回true, 那么一定返回false 
				}
				else return false;//如果不等于则直接返回false 
			}
		}
		else if (spe_pos == spenum){
			if (flag1 == 1) {
				//当最后一个通配符是"*"的时候 
				if (got_pos - 1 == len1) return true;//若最后一个字符是"*" 
				if (Work(got_pos, i, spe_pos + 1)) return true;
				else return false;
				//将got_pos到len1的子串与i到len2的子串比较 
			}
		}
	} 
	return false;
}

int main() {
	base[0] = 1;
	for (int i = 1; i <= 114514; ++ i) {
		base[i] = base[i - 1] * 13331;
	}
	scanf("%s", temp);
	len1 = strlen(temp);
	for (int i = 0; i < len1; ++ i) {
		got[i + 1] = temp[i];
	}
	for (int i = 1; i <= len1; ++ i) {
		pre1[i] = pre1[i - 1] * base[1] + (ull)got[i];
		if (got[i] == '*') {
			spe[++ spenum][0] = i;
		}
		else {
			spe[++ spenum][1] = i;
		}
	}
	cin >> t;
	while (t --) {
		scanf("%s", temp);
		len2 = strlen(temp);
		for (int i = 0; i < len2; ++ i) {
			ask[i + 1] = temp[i];
		}
		for (int i = 1; i <= len2; ++ i) {
			pre2[i] = pre2[i - 1] * base[1] + (ull)ask[i];
		}
		bool flag = Work(1, 1, 0);
	}
}

标签:return,P3167,Luogu,通配符,pos,got,CQOI2014,false,spe
From: https://www.cnblogs.com/jueqingfeng/p/17472077.html

相关文章

  • Luogu P4591 [TJOI2018]碱基序列
    [TJOI2018]碱基序列题目描述小豆参加了生物实验室。在实验室里,他主要研究蛋白质。他现在研究的蛋白质是由\(k\)个氨基酸按一定顺序构成的。每一个氨基酸都可能有\(a\)种碱基序列\(s_{i,j}\)构成。现在小豆有一个碱基串\(s\),小豆想知道在这个碱基上都多少中不同的组合方式可能得......
  • Luogu P4159 [SCOI2009] 迷路
    [SCOI2009]迷路题目背景windy在有向图中迷路了。题目描述该有向图有\(n\)个节点,节点从\(1\)至\(n\)编号,windy从节点\(1\)出发,他必须恰好在\(t\)时刻到达节点\(n\)。现在给出该有向图,你能告诉windy总共有多少种不同的路径吗?答案对\(2009\)取模。注意:windy......
  • Luogu P1939 【模板】矩阵加速(数列)
    【模板】矩阵加速(数列)题目描述已知一个数列\(a\),它满足:\[a_x=\begin{cases}1&x\in\{1,2,3\}\\a_{x-1}+a_{x-3}&x\geq4\end{cases}\]求\(a\)数列的第\(n\)项对\(10^9+7\)取余的值。输入格式第一行一个整数\(T\),表示询问个数。以下\(T\)行,每行一个正......
  • Luogu P3390 【模板】矩阵快速幂
    【模板】矩阵快速幂题目背景一个\(m\timesn\)的矩阵是一个由\(m\)行\(n\)列元素排列成的矩形阵列。即形如\[A=\begin{bmatrix}a_{11}&a_{12}&\cdots&a_{1n}\\a_{21}&a_{22}&\cdots&a_{2n}\\\vdots&\vdots&\ddots&......
  • Luogu B2105 矩阵乘法(模板)
    矩阵乘法题目描述计算两个矩阵的乘法。\(n\timesm\)阶的矩阵\(A\)乘以\(m\timesk\)阶的矩阵\(B\)得到的矩阵\(C\)是\(n\timesk\)阶的,且\(C[i][j]=A[i][0]\timesB[0][j]+A[i][1]\timesB[1][j]+\)……\(+A[i][m-1]\timesB[m-1][j](C[i][j]\)表示\(C\)......
  • Luogu P4219 [BJOI2014]大融合
    [BJOI2014]大融合题目描述小强要在\(N\)个孤立的星球上建立起一套通信系统。这套通信系统就是连接\(N\)个点的一个树。这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量。例如,在上图中,现在一共有了\(5\)......
  • Luogu P4577 [FJOI2018] 领导集团问题
    [FJOI2018]领导集团问题题目描述一个公司的组织领导架构可以用一棵领导树来表示。公司的每个成员对应于树中一个结点\(v_i\),且每个成员都有响应的级别\(w_i\)。越高层的领导,其级别值\(w_i\)越小。树中任何两个结点之间有边相连,则表示与结点相应的两个成员属于同一部门。领......
  • Luogu P5446 [THUPC2018] 绿绿和串串
    根据题目能发现一个性质,设转化前的字符串为\(s\),转化后的字符串为\(s'\),则\(s'_{|s|}\)为\(s'\)的中心,即\(s'_{|s|}\)求出来的回文串左边界为\(1\)右边界为\(|s'|\)找出这个性质就挺简单了,考虑先对给出的\(S\)用\(\text{manacher}\)求出每个节点\(i\)对应的左边......
  • Luogu P3224 [HNOI2012]永无乡
    [HNOI2012]永无乡题目描述永无乡包含\(n\)座岛,编号从\(1\)到\(n\),每座岛都有自己的独一无二的重要度,按照重要度可以将这\(n\)座岛排名,名次用\(1\)到\(n\)来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛\(a\)出发经过若干座(含\(0\)......
  • [刷题笔记] Luogu P3073 [USACO13FEB]Tractor S
    ProblemSolution和汽车拉力比赛差不多,思路都是二分,二分\(d\),但是汽车拉力比赛从一个路标开始搜即可,本题没有给定起点。一条合法路径起点是未知的,不得随便从一个点开始搜,否则可能找不到正确路径。怎么处理呢?容易想到对于每一个二分的\(d\),开一个\(n^2\)的循环,从每一个点开始搜......