3507: [Cqoi2014]通配符匹配

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

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

Input

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

Output

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

Sample Input

*aca?ctc
6
acaacatctc
acatctc
aacacatctc
aggggcaacacctc
aggggcaacatctc
aggggcaacctct

Sample Output

YES
YES
YES
YES
YES
NO

HINT

对于1 00%的数据
  ·字符串长度不超过1 00000
  ·  1 <=n<=100
  ·通配符个数不超过10

题解:

考场打暴力打炸了……

不过在后来改题的时候我发现了暴力思路的一个大问题……我们还是直接讲正解吧

题目给的通配符有2种,一种是’*’,它可以伸展;一种是‘?’,它的长度固定;

不难发现,给我们的处理带来难度的是'*',因为他的长度不确定;

但转念一想,如果除了*,其他的都能匹配,那*也就能匹配了.

注意到通配符个数<=10,那么我们可以先按照*,把原串分成一些包含'?'和字母的段.

而对于每一段,只要其中的所有小字符串成功匹配,并且符合'?'对长度的要求,这一段就匹配成功了

所以我们再在每一段里,按照'?'再分为几小块只含字母的串,并且分别求出hash值;同时求出文本串的hash值.

在匹配的时候,对于某一段,枚举起点,看在这一段在哪里可以匹配.

由于对于段间的枚举,影响因素只有*,所以匹配点肯定越靠前越好,因此这里可以贪心,即找到最靠前的匹配点即可停止.

而对于段内比较,利用刚才求的hash值比较就好.

代码见下:

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
typedef unsigned long long LL;
const int N=;
const int mod1=;
int n,lens,len,cnt,cnt1[];
char s[N],text[N];
LL block[][],h[N],mi[N];
int l[][],num[];
inline LL g_hash(int l,int r){return h[r]-h[l-]*mi[r-l+];}
inline bool match(int i,int k)
{
for(int j=;j<=num[k];j++)
{
if(l[k][j]==){i++;continue;}
if(block[k][j]!=g_hash(i,i+l[k][j]-))return ;
i+=l[k][j]+;
}
return ;
}
bool judge()
{
if(!cnt)
{
if(len!=lens)return ;
for(int i=;i<=len;i++)
if(s[i]!=text[i]&&s[i]!='?')return ;
return ;
}
if(len<(cnt1[]-)+(lens-cnt1[cnt]))return ;
for(int i=;i<cnt1[];i++)if(s[i]!=text[i]&&s[i]!='?')return ;
for(int i=lens,j=len;i>cnt1[cnt];i--,j--)if(s[i]!=text[j]&&s[i]!='?')return ;
for(int i=;i<=len;i++)
h[i]=h[i-]*mod1+text[i];
int i=cnt1[],line=len-(lens-cnt1[cnt])+;
for(int k=;k<=cnt;k++)
{
for(;i<=line;i++)
if(match(i,k))break;
i+=cnt1[k]-cnt1[k-]-;
if(i>line)return ;
}
return ;
}
int main()
{
scanf("%s",s+);lens=strlen(s+);
mi[]=;for(int i=;i<=lens;i++)mi[i]=mi[i-]*mod1;
for(int i=;i<=lens;i++)
if(s[i]=='*')cnt1[++cnt]=i;
for(int i=;i<=cnt;i++)
{
num[i]=;
for(int j=cnt1[i-]+;j<cnt1[i];j++)
{
if(s[j]=='?'){num[i]++;continue;}
l[i][num[i]]++;
block[i][num[i]]=block[i][num[i]]*mod1+s[j];
}
}
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",text+);len=strlen(text+);
if(judge())printf("YES\n");
else printf("NO\n");
}
}

BZOJ3507

[BZOJ3507]通配符匹配的更多相关文章

  1. [CQOI2014][bzoj3507] 通配符匹配 [字符串hash+dp]

    题面 传送门 思路 0x01 KMP 一个非常显然而优秀的想法:把模板串按照'*'分段,然后对于每一段求$next$,'?'就当成可以对于任意字符匹配就行了 对于每个文本串,从前往后找第一个可以匹配的 ...

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

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

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

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

  4. BZOJ3507 [Cqoi2014]通配符匹配

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

  5. BZOJ3507 [Cqoi2014]通配符匹配 【哈希 + 贪心】

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

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

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

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

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

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

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

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

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

随机推荐

  1. HTTP请求方式:GET和POST的比较

    GET和POST是HTTP的两个常用方法 什么是HTTP? 超文本传输协议(HyperText Transfer Prptocol-HTTP)是一个设计来使客户端和服务器顺利进行通讯的协议. HTTP ...

  2. scala : 类型与类

    scala类型系统:1) 类型与类 在Java里,一直到jdk1.5之前,我们说一个对象的类型(type),都与它的class是一一映射的,通过获取它们的class对象,比如 String.class ...

  3. 支付宝、微信、QQ 收款二维码三合一

    最近折腾了一下合并收款码,简单记录一下折腾的过程,方法不唯一,只是提供一种思路,如果各位大佬有更加简单粗暴的办法,那就更好了. 原理 首先解析出三个二维码的内容,用 Nginx 判断 User age ...

  4. OpenCL入门:(二:用GPU计算两个数组和)

    本文编写一个计算两个数组和的程序,用CPU和GPU分别运算,计算运算时间,并且校验最后的运算结果.文中代码偏多,原理建议阅读下面文章,文中介绍了OpenCL相关名词概念. http://opencl. ...

  5. 动态权限<一>基本介绍

    android 6.0以上为了保护用户的隐私,和以往被人诟病的权限机制,确立了新的权限机制.从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授 ...

  6. 第七章移动互联网与移动IP

    第七章移动互联网与移动IP 本章延续前几章节,对该章节内容进行归纳总结. 文章中的Why表示产生的背景,也就是说为什么会产生该技术,What表示该技术是什么,How表示该技术是如何使用的.以下将用字母 ...

  7. idea 临时文件

    idea可以直接创建一个 scratch file (mac os快捷键 cmd+shift+n) 在里面可以自由的编辑文档, 配合vim使用很方便, 我使用的频率还比较高. 大概是这样的. 这个临时 ...

  8. 2.5星|《哈佛商学院管理与MBA案例全书》:书名太唬人了,依据中文经管书汇编整理而成

    哈佛商学院管理与MBA案例全书(套装十册) 看到最后,列出的参考书目中全部是中文经管书,才明白这本书不是哈佛商学院出版的,是国内的编辑做的汇编.参考书目中除了中文经管书之外,还有一套<哈佛商学院 ...

  9. python编辑三级目录

    一.需求分析 三级目录要能够实现以下要求: 显示根目录,任何子目录中都可以通过输入b字符来返回根目录 任何子目录中都可以通过输入q字符来返回上一级目录 主目录进入子目录后,系统能够打印子目录,根据指打 ...

  10. DNS递归查询与迭代查询

    注:一般TCP/IP的应用层或者OSI的会话.表示.应用层把数据称为数据或者信息,到了传输层把数据称为报文,到了最底层就是比特流了也就是字节流 DNS递归查询与迭代查询   基础知识 1.域名系统 2 ...