首先可以对n个目标串单独进行处理。

对于每个目标串,考虑把模式串按'*'进行划分为cnt段。首尾两段一定得于原串进行匹配。剩下的cnt-2段尽量与最靠左的起点进行匹配。

对于剩下的cnt-2段。每段又可以通过‘?’划分为k个子串。对每个子串求出hash值。然后通过枚举起点与目标串的某个区间的hash进行判断。

就可以在O(k)的时间进行每一次的枚举了。对于目标串区间的hash值。可以通过预处理hash前缀进行O(1)询问。

而最多进行len次枚举。所以总复杂度为O(n*len*k).

另外判断子串匹配目标串的区间用AC自动机也是可以的。

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi 3.1415926535
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... char str[N], ss[N];
int hs[N], shs[N], xing[], pos, bg, ed;
struct Node{int x, len; bool flag;}node[]; int get_hash(int l, int r){return shs[r]-shs[l-]*hs[r-l+];}
bool check(int be, int L){
int sum=;
FOR(i,,L) if (node[i].flag) sum+=node[i].x; else sum+=node[i].len;
if (be+sum>ed+) return false;
FOR(i,,L) {
if (node[i].flag) be+=node[i].x;
else {
if (get_hash(be,be+node[i].len-)!=node[i].x) return false;
be+=node[i].len;
}
}
return true;
}
bool sol(){
int num, sum, l, cnt, ll;
FOR(i,,pos) {
if (xing[i]-xing[i-]<=) continue;
sum=num=l=ll=cnt=;
FOR(j,xing[i-]+,xing[i]-) {
if (str[j]=='?') {
++num;
if (l) node[++cnt].x=sum, node[cnt].len=l; node[cnt].flag=, sum=l=;
}
else {
sum=sum*MOD+str[j]; ++l;
if (num) node[++cnt].x=num, node[cnt].flag=, num=;
}
}
if (l) node[++cnt].x=sum, node[cnt].len=l; node[cnt].flag=, sum=l=;
if (num) node[++cnt].x=num, node[cnt].flag=, num=;
while (bg<=ed&&!check(bg,cnt)) ++bg;
if (!check(bg,cnt)) return false;
FOR(i,,cnt) if (node[i].flag) ll+=node[i].x; else ll+=node[i].len;
bg+=ll;
}
return true;
}
int main ()
{
hs[]=; FO(i,,N) hs[i]=hs[i-]*MOD;
scanf("%s",str+);
int T;
scanf("%d",&T);
while (T--) {
scanf("%s",ss+);
pos=; bg=; ed=strlen(ss+);
for (int i=; ss[i]; ++i) shs[i]=shs[i-]*MOD+ss[i];
int l=, r=strlen(str+);
int flag=;
while (str[l]!='*'&&l<=r&&bg<=ed) {
if (str[l]=='?'||str[l]==ss[bg]) ++l, ++bg;
else {flag=; break;}
}
while (str[r]!='*'&&l<=r&&bg<=ed) {
if (str[r]=='?'||str[r]==ss[ed]) --r, --ed;
else {flag=; break;}
}
if (flag) {puts("NO"); continue;}
FOR(i,l,r) if (str[i]=='*') xing[++pos]=i;
if (pos==&&bg<=ed) {puts("NO"); continue;}
puts(sol()?"YES":"NO");
}
return ;
}

BZOJ 3507 通配符匹配(贪心+hash或贪心+AC自动机)的更多相关文章

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

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

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

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

  3. [BZOJ3507][CQOI2014]通配符匹配(DP+Hash)

    显然f[i][j]表示S匹配到第i个通配符,T匹配到第j个字符,是否可行. 一次一起转移两个通配符之间的所有字符,Hash判断. 稍微有点细节.常数极大卡时过排名倒数,可能是没自然溢出的原因. #in ...

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

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

  5. BZOJ 1444 [JSOI2009]有趣的游戏 (Trie图/AC自动机+矩阵求逆)

    题目大意:给你$N$个长度相等且互不相同的模式串,现在有一个字符串生成器会不断生成字符,其中每个字符出现的概率是$p_{i}/q_{i}$,当生成器生成的字符串包含了某个模式串,则拥有该模式串的玩家胜 ...

  6. BZOJ 2754: [SCOI2012]喵星球上的点名 [AC自动机+map+暴力]

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1902  Solved: 837[Submit][St ...

  7. 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

    [题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...

  8. BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题目大意] 给出一个打印的过程,'a'-'z'表示输入字母,P表示打印该字符串 ...

  9. BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机、树状数组)

    吐槽: 为啥很多人用AC自动机暴力跳都过了?复杂度真的对么? 做法一: AC自动机+树状数组 姓名的问题,中间加个特殊字符连起来即可. 肯定是对点名串建AC自动机(map存儿子),然后第一问就相当于问 ...

随机推荐

  1. day 3 创建窗口,移动-函数版

    1.创建窗口 #-*- coding:utf-8 -*- import pygame import time def main(): #1.创建窗口 screen = pygame.display.s ...

  2. dubbo之基础应用

    一.Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务模型的角度来看,Dubbo采用的是一种非常简单 ...

  3. 使用Unity创建依赖注入

        这篇文章翻译自<Dependency Injection With Unity>第三章.文中提到的类似"前几节"的内容您不必在意,相信您可以看懂的. P.S:如 ...

  4. 关于maven项目中修改的JS不生效的解决方案

    1. 问题描述 昨天下午博主在开发学习的过程中,碰到一个修改了JS无法生效的问题,折腾我不少的时间,现将百度到的解决方案总结一下,以便下次碰到类似问题能够最快的找到解决方案 2 解决方案 2.1 方案 ...

  5. stm32之SPI通信协议

    SPI (Serial Peripheral interface),顾名思义就是串行外围设备接口.SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为P ...

  6. 十分钟掌握pandas(pandas官方文档翻译)

    十分钟掌握pandas 文档版本:0.20.3 这是一个对pandas简短的介绍,适合新用户.你可以在Cookbook中查看更详细的内容. 通常,我们要像下面一样导入一些包. In [1]: impo ...

  7. 使用eclipse创建maven项目出现的一个问题

    错误信息 This error occurs when you employ a plugin that Maven could not download. Possible causes for t ...

  8. [转载]Java集合框架的常见面试题

    http://www.jfox.info/40-ge-java-ji-he-lei-mian-shi-ti-he-da-an 整理自上面链接: Java集合框架为Java编程语言的基础,也是Java面 ...

  9. Java中String类

    String类 一.String类的用途 对字符串的存储与操作,即包含多个字符的字符数据,这个String类提供了数值不可改变的字符串. String类为什么不可改变的字符串,因为String类是fa ...

  10. 二:HDFS 命令指南

    命令具体选项请参考: http://hadoop.apache.org/docs/r2.6.3/hadoop-project-dist/hadoop-hdfs/HDFSCommands.html   ...