题意

本题的意思就是给出一段带有 $ ? $ 与 \(*\) 的字符串

(在下面称为\(s\)),

$ ? $ 必须占据一个字符位置, \(*\) 可以占据任意位置,

求下面给出几段(在下面称为\(ss\))中能够匹配的字符串。

思路


前言

本题最可恶的一点是,如果s的第一段/最后一段是字符,那么ss中最开始/最后也必须是一样的字符。

另外,本题我使用了hash + 前缀,如果不太熟悉的话可以了解一下~传送门

举个栗子~

如样例,s为*aca?ctc,我们就可以将它分为

\(*\) ,aca, $ ? $ ,ctc 共四段。

对于每一段,我们用一个add数组来判断它的种类,

用co记录它的段数,字符串对应2,\(*\) 对应1,$ ? $ 对应0:


scanf("%s",s+1);lens=strlen(s+1);
if(s[1]<'a'||s[1]>'z')co=0;else add[1]=2;
for(int i=1;i<=lens;i++)
{
if(s[i]>='a'&&s[i]<='z')
{
len[co]++;
f[co]=f[co]*131+s[i];
}
else if(s[i]=='*') {add[++co]=1;if(i!=lens&&s[i+1]>='a'&&s[i+1]<='z')add[++co]=2;}
else{co++;if(i!=lens&&s[i+1]>='a'&&s[i+1]<='z')add[++co]=2;}
}

注意,由于开头字符不好判断,所以这里加了一个特判,

来记录开头是字符串的情况。

判断

预处理好了,那么,如何进行判断呢?

这里,我用了 $ doit $ 与 \(ask\) 两个自定义函数,

doit用来对可以自由匹配的字符种类进行判断处理,

ask用来对“ ? ”后的字符进行判断处理。

两个函数中都使用了key,k两个参数,

key记录了到哪个字符(指针),k记录了到第几段。

对于doit:


void doit(int key,int k)
{
if(k>co){can=1;return;}//段数数完了,说明满足条件;
if(add[k]==2)//字符
{
for(int i=key+len[k]-1;i<=le;i++)
if(ff[i]-ff[i-len[k]]*p[len[k]]==f[k])//寻找符合的解进行doit;
{doit(i+1,k+1);if(can)return;}
return;
}
if(add[k]==1)//星号
{
doit(key,k+1);
if(can)return;
return;
}
if(add[k]==0)//问号
{
ask(key+1,k+1);return;
}
}

对于ask:


void ask(int key,int k)
{
if(k>co){can=1;return;}
if(add[k]==2)
{
if(ff[key+len[k]-1]-ff[key-1]*p[len[k]]==f[k])doit(key+len[k],k+1);
}
else
{
if(add[k]==1){if(add[k+1]==0){
for(int i=key+2;i<=le;i++)
if(ff[i+len[k+2]-1]-ff[i-1]*p[len[k+2]]==f[k+2])doit(i+len[k+2],k+3);}
doit(key,k+1);}//星号,判断下一个是不是问号
如果是问号就要找到能够匹配的子串进行doit;
else ask(key+1,k+1);//问号继续ask;
}
}

收尾

到这里,万事俱备,只欠东风,进行我们华丽的结束吧~

接下来就该读入与判断了:

	p[0]=1;
for(int i=1;i<=100000;i++)p[i]=p[i-1]*131;
int n=read();
while(n--)
{can=0;
scanf("%s",ss+1);le=strlen(ss+1);
for(int i=1;i<=le;i++)ff[i]=ff[i-1]*131+ss[i];
if(add[1]==2)if(ff[len[1]]-ff[0]*p[len[1]]!=f[1]){printf("NO\n");continue;}//前言中说的特殊情况
if(add[co]==2)if(ff[le]-ff[le-len[co]]*p[len[co]]!=f[co]){printf("NO\n");continue;}
doit(1,1);
if(can)printf("YES\n");else printf("NO\n");
}
return 0;

CODE


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define ull unsigned long long
int read(){int x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x;}
char s[100005],ss[100005];
int lens,len[25],co=1,le,k,key,cnt,add[25];bool can;
ull f[25],ff[100010],p[100010];
void ask(int,int);
void doit(int,int);
void ask(int key,int k)
{
if(k>co){can=1;return;}
if(add[k]==2)
{
if(ff[key+len[k]-1]-ff[key-1]*p[len[k]]==f[k])doit(key+len[k],k+1);
}
else
{
if(add[k]==1){if(add[k+1]==0){for(int i=key+2;i<=le;i++)if(ff[i+len[k+2]-1]-ff[i-1]*p[len[k+2]]==f[k+2])doit(i+len[k+2],k+3);}doit(key,k+1);}
else ask(key+1,k+1);
}
}
void doit(int key,int k)
{
if(k>co){can=1;return;}
if(add[k]==2)
{
for(int i=key+len[k]-1;i<=le;i++)
if(ff[i]-ff[i-len[k]]*p[len[k]]==f[k])
{doit(i+1,k+1);if(can)return;}
return;
}
if(add[k]==1)
{
doit(key,k+1);
if(can)return;
return;
}
if(add[k]==0)
{
ask(key+1,k+1);return;
}
}
int main()
{
scanf("%s",s+1);lens=strlen(s+1);
if(s[1]<'a'||s[1]>'z')co=0;else add[1]=2;
for(int i=1;i<=lens;i++)
{
if(s[i]>='a'&&s[i]<='z')
{
len[co]++;
f[co]=f[co]*131+s[i];
}
else if(s[i]=='*') {add[++co]=1;if(i!=lens&&s[i+1]>='a'&&s[i+1]<='z')add[++co]=2;}
else{co++;if(i!=lens&&s[i+1]>='a'&&s[i+1]<='z')add[++co]=2;}
}
p[0]=1;
for(int i=1;i<=100000;i++)p[i]=p[i-1]*131;
int n=read();
while(n--)
{can=0;
scanf("%s",ss+1);le=strlen(ss+1);
for(int i=1;i<=le;i++)ff[i]=ff[i-1]*131+ss[i];
if(add[1]==2)if(ff[len[1]]-ff[0]*p[len[1]]!=f[1]){printf("NO\n");continue;}
if(add[co]==2)if(ff[le]-ff[le-len[co]]*p[len[co]]!=f[co]){printf("NO\n");continue;}
doit(1,1);
if(can)printf("YES\n");else printf("NO\n");
}
return 0;
}

结语

这道题我也调了有好久了,甚至都有些舍不得了,所以写下了本篇题解,也是我的第一篇题解

如果对你有帮助,求个赞qwq

LuoguP3167通配符匹配的更多相关文章

  1. bzoj 3507: [Cqoi2014]通配符匹配

    Description 几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户.最常见的通配符有两个,一个是星号(“”’),可以匹配0个及以上的任意字符:另一个是问号(“?”),可 ...

  2. 【BZOJ-3507】通配符匹配 DP + Hash

    3507: [Cqoi2014]通配符匹配 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 372  Solved: 156[Submit][Statu ...

  3. [Swift]LeetCode44. 通配符匹配 | Wildcard Matching

    Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '? ...

  4. 【BZOJ3507】通配符匹配(哈希,动态规划)

    [BZOJ3507]通配符匹配(哈希,动态规划) 题面 BZOJ 题解 对于匹配唯一存在影响的只有通配符,而\(?\)的影响也并不大,所以唯一需要仔细考虑的是\(*\). 考虑一个\(dp\),设\( ...

  5. LeetCode(44): 通配符匹配

    Hard! 题目描述: 给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配. '?' 可以匹配任何单个字符. '*' 可以匹配任意字符串(包括空字符串). ...

  6. [BZOJ3507]通配符匹配

    3507: [Cqoi2014]通配符匹配 Time Limit: 10 Sec  Memory Limit: 128 MB Description 几乎所有操作系统的命令行界面(CLI)中都支持文件 ...

  7. [LeetCode][Facebook面试题] 通配符匹配和正则表达式匹配,题 Wildcard Matching

    开篇 通常的匹配分为两类,一种是正则表达式匹配,pattern包含一些关键字,比如'*'的用法是紧跟在pattern的某个字符后,表示这个字符可以出现任意多次(包括0次). 另一种是通配符匹配,我们在 ...

  8. WildcardMatching和Regex,通配符匹配和正则表达式匹配

    WildcardMatching:通配符匹配 算法分析: 1. 二个指针i, j分别指向字符串.匹配公式. 2. 如果匹配,直接2个指针一起前进. 3. 如果匹配公式是*,在字符串中依次匹配即可. 注 ...

  9. BZOJ3507 [Cqoi2014]通配符匹配

    题意 几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户.最常见的通配符有两个,一个是星号("*"),可以匹配0个及以上的任意字符:另一个是问号(" ...

随机推荐

  1. centos安装报错:license information (license not accepted)

    前言:在最近部署的centos系统发现个问题 出现报错:安装配置完成后,重启虚拟机出现license  information  (license not accepted) 截图: 解决方案: 在界 ...

  2. makedown语法小记

    1.标题,支持六级 # 这是一级标题 ## 这是二级标题 ### 这是三级标题 2.斜体 *这是斜体* 3.加粗 **这是加粗** 4.斜体加粗 ***这是斜体加粗*** 5.删除线 ~~这是删除线~ ...

  3. 等了半年,m1芯片原生支持的.NET IDE出现了

    m1芯片是苹果2020年发布的一款基于arm的桌面芯片,目前已经应用在MacBook Air .MacBook Pro.IMac.Ipad等设备上.可以说整个苹果生态圈都在去intel化. 今年年初跟 ...

  4. 入门 - SpringBoot 2.x 使用 JWT

    JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理和用法 一.跨域认证遇到的问题 由于多终端的出现,很多的站点通过 web api restful 的形式对外 ...

  5. mac设置终端命令行别名alias(git、npm)

    别名(alias)通常被用作对一串或单个命令的简称.懒人必备!当常用到命令行操作的时候,每次输入一长串命令,不厌其烦,自然想到了用简称代替.这里主要介绍两种mac设置别名alias的方式. mac 设 ...

  6. kubernetes/k8s CSI分析-容器存储接口分析

    更多 k8s CSI 的分析,可以查看这篇博客kubernetes ceph-csi分析,以 ceph-csi 为例,做了详细的源码分析. 概述 kubernetes的设计初衷是支持可插拔架构,从而利 ...

  7. windows上安装python3里没有pip问题,解决办法!

    安装python3: 1.下载python:https://www.python.org/downloads/ 2.安装:   3.安装完成进cmd里验证,但发现无pip包 所以操作步骤如下: 1.下 ...

  8. JavaScript之DOM、DOM树

    一 DOM JavaScript操作网页的接口,全称为"文档对象模型"(Document Object Model). 有这几个概念:文档.元素.节点 整个文档是一个文档节点 每个 ...

  9. pointnet.pytorch代码解析

    pointnet.pytorch代码解析 代码运行 Training cd utils python train_classification.py --dataset <dataset pat ...

  10. 大数据学习(14)—— HBase进阶

    HBase读写流程 在网上找了一张图,这个画的比较简单,就拿这个图来说吧. 写流程 1.当Client发起一个Put请求时,首先访问Zookeeper获取hbase:meta表. 2.从hbase:m ...