「题解报告」 P3167 [CQOI2014]通配符匹配

思路

*?显然无法直接匹配,但是可以发现「通配符个数不超过 \(10\) 」,那么我们可以考虑分段匹配。

我们首先把原字符串分成多个以一个通配符开头的字符串,如将 happy*birthdey?xingchen 分成:

happy
*birthday
?xingchen

然后设原串有 \(m\) 个通配符, \(op_i\) 表示分出来的第 \(i\) 个串前的通配符(\(0\) 没有,\(1\) 是?,\(2\) 是*),\(len_i\) 表示分出来的第 \(i\) 个串的长度,\(f_{i,j}\) 表示分出来的第 \(i\) 个串的结尾能否匹配上当前查询的字符串的位置 \(j\)。

则转移方程显然为:

\[f_{i,j}=
\begin{cases}
f_{i-1,j-len_i}&op_i=0\\
f_{i-1,j-len_i-1}&op_i=1\\
\sum_{k=0}^{j-len}f_{i-1,j-len_i}&op_i=2\\
\end{cases}
\]

能否转移直接用 Hash \(\Theta(1)\) 比较即可。

初始状态 \(f_{0,0}=1\),答案为 \(f_{m,\left|S\right|}\),时间复杂度 \(\Theta(mn\left|S\right|)\)。

代码

const ll N=1e5+10,inf=1ll<<40;
ll T,n,m=1,ln,ans;
ll a1[20],a2[20],len[20],op[20];
ll f[20][N],sm[N];
char s[N],t[N];
class Hash{
public:
const ll P1=315716521,P2=475262633;
ll h1[N],h2[N],z1[N],z2[N];
inline void Init(char *s){
z1[0]=z2[0]=1;
ll length=strlen(s+1);
_for(i,1,length){
z1[i]=z1[i-1]*233%P1;
z2[i]=z2[i-1]*233%P2;
h1[i]=(h1[i-1]*233+s[i]-'a'+1)%P1;
h2[i]=(h2[i-1]*233+s[i]-'a'+1)%P2;
}
return;
}
inline ll GetHash1(ll l,ll r){return (h1[r]-h1[l-1]*z1[r-l+1]%P1+P1)%P1;}
inline ll GetHash2(ll l,ll r){return (h2[r]-h2[l-1]*z2[r-l+1]%P2+P2)%P2;}
}b;
namespace SOLVE{
inline ll rnt(){
ll x=0,w=1;char c=getchar();
while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*w;
}
inline ll GetA1(char *awa){
ll hash_val=0;
ll length=strlen(awa+1);
_for(i,1,length)hash_val=(hash_val*233+awa[i]-'a'+1)%b.P1;
return hash_val;
}
inline ll GetA2(char *awa){
ll hash_val=0;
ll length=strlen(awa+1);
_for(i,1,length)hash_val=(hash_val*233+awa[i]-'a'+1)%b.P2;
return hash_val;
}
inline void Pre(){
char qwq[N];
_for(i,1,n){
if(s[i]=='?'||s[i]=='*'){
if(i==1)--m;
a1[m]=GetA1(qwq);
a2[m]=GetA2(qwq);
memset(qwq,0,sizeof(qwq));
op[++m]=(s[i]=='?')?1:2;
}
else qwq[++len[m]]=s[i];
}
a1[m]=GetA1(qwq);
a2[m]=GetA2(qwq);
return;
}
inline bool Check(ll a,ll i){
if(a1[a]!=b.GetHash1(i-len[a]+1,i))return 0;
if(a2[a]!=b.GetHash2(i-len[a]+1,i))return 0;
return 1;
}
inline void PP(){
f[0][0]=1;
_for(i,0,ln)sm[i]=1;
_for(i,1,m){
_for(j,0,ln)f[i][j]=0;
for_(j,ln,len[i]){
if(Check(i,j)){
if(op[i]==0)f[i][j]=f[i-1][j-len[i]];
else if(op[i]==1)f[i][j]=f[i-1][j-len[i]-1];
else f[i][j]=sm[j-len[i]];
}
}
sm[0]=0;
_for(j,1,ln)sm[j]=sm[j-1]|f[i][j];
}
return;
}
inline void In(){
scanf("%s",s+1);
n=strlen(s+1),Pre();
T=rnt();
while(T--){
scanf("%s",t+1);
b.Init(t),ln=strlen(t+1);
PP(),puts(f[m][ln]?"YES":"NO");
}
return;
}
}

「题解报告」 P3167 [CQOI2014]通配符匹配的更多相关文章

  1. P3167 [CQOI2014]通配符匹配 题解

    题目 题目大意 给出一个字符串,其中包含两种通配符 ‘?’和 ‘*’ ,‘?’可以代替一个字符,‘*’可以代替一个字符串(长度可以为0) 然后给出几个字符转,判断能否用给出的字符串表示出来 样例解释 ...

  2. 「题解报告」P4577 [FJOI2018]领导集团问题

    题解 P4577 [FJOI2018]领导集团问题 题解区好像没有线段树上又套了二分的做法,于是就有了这片题解. 题目传送门 怀着必 WA 的决心交了两发,一不小心就过了. 题意 求一个树上最长不下降 ...

  3. 「题解报告」P2154 虔诚的墓主人

    P2154 虔诚的墓主人 题解 原题传送门 题意 在 \(n\times m\) 一个方格上给你 \(w\) 个点,求方格里每个点正上下左右各选 \(k\) 个点的方案数. \(1 \le N, M ...

  4. 「题解报告」SP16185 Mining your own business

    题解 SP16185 Mining your own business 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...

  5. 「题解报告」Blocks

    P3503 Blocks 题解 原题传送门 思路 首先我们可以发现,若 \(a_l\) ~ \(a_r\) 的平均值大于等于 \(k\) ,则这个区间一定可以转化为都大于等于 \(k\) 的.我们就把 ...

  6. 「题解报告」P3354

    P3354 题解 题目传送门 一道很恶心的树形dp 但是我喜欢 题目大意: 一片海旁边有一条树状的河,入海口有一个大伐木场,每条河的分叉处都有村庄.建了伐木场的村庄可以直接处理木料,否则要往下游的伐木 ...

  7. 「题解报告」CF1067A Array Without Local Maximums

    大佬们的题解都太深奥了,直接把转移方程放出来让其他大佬们感性理解,蒟蒻们很难理解,所以我就写了一篇让像我一样的蒟蒻能看懂的题解 原题传送门 动态规划三部曲:确定状态,转移方程,初始状态和答案. --神 ...

  8. P3167 [CQOI2014]通配符匹配

    吐槽 本来是去写AC自动机的,然后发现数据范围每个串100000,有100个串(???),连塞进trie树里都塞不进去,玩个鬼的AC自动机啊,tag不要乱打啊 最后拿字符串hash+爆搜一发搜过去了. ...

  9. 「题解报告」P7301 【[USACO21JAN] Spaced Out S】

    原题传送门 神奇的5分算法:直接输出样例. 20分算法 直接把每个点是否有牛的状态DFS一遍同时判断是否合法,时间复杂度约为\(O(2^{n^2})\)(因为有判断合法的剪枝所以会比这个低).而在前四 ...

随机推荐

  1. robotframework之环境安装

    一.安装python2.7环境,python --version查询python安装的版本 二.setuptools安装

  2. Windows-matlab简易安装-用于数字图像处理

    安装 下载链接 解压文件得到 双击setup.exe 主要注意几点 使用文件安装密匙 只需安装这三个即可 将两个文件夹里面的dll文件复制到安装目录的 /bin/win64 目录 两个 .lic 文件 ...

  3. Vue.js与ElementUI搭建无限级联层级表格组件

    前言 今天,回老家了.第一件事就是回家把大屏安排上,写作的感觉太爽了,终于可以专心地写文章了.我们今天要做的项目是怎么样搭建一个无限级联层级表格组件,好了,多了不多说,赶快行动起来吧!项目一览 到底是 ...

  4. SQL报了一个不常见的错误,让新来的实习生懵了

    摘要:前些天一个很简单的SQL报了一个不常见的错误. 本文分享自华为云社区<记一次mysql关联查询格式冲突问题[五月04]>,作者: KevinQ . 问题起源 作为CRUD程序员,最常 ...

  5. Linux命令格式、终端类型和获取帮助的方法

    Linux用户类型 Root用户:超级管理员,权限很大 普通用户:权限有限 终端 terminal 终端类型 物理终端:鼠标.键盘.显示器 虚拟终端:软件模拟出来的终端 控制台终端: /dev/con ...

  6. java SWT中Label实时刷新当前时间

    同样最近在开发swt的一个项目,业务中的一个功能模块类似百度网盘的上传进度条 0/80. 即已上传0个,总共80个.效果展示要的就是实时刷新,2/80呀,15/80呀,针对这个,就有了这篇文章. 下面 ...

  7. linux下的nginx日志自动备份压缩--日志切割机

    部署完毕nginx之后,发现自己的/var/log/nginx/*log的日志不会压缩,一直都是一个文本写日志, 时间久了,日志文件内存过于增加,将会导致在日志添加过程效率降低,延长时间. 默认安装的 ...

  8. NC50528 滑动窗口

    NC50528 滑动窗口 题目 题目描述 给一个长度为N的数组,一个长为K的滑动窗体从最左端移至最右端,你只能看到窗口中的K个数,每次窗体向右移动一位,如下图: 你的任务是找出窗体在各个位置时的最大值 ...

  9. labview从入门到出家6(进阶篇)--移位寄存器的使用

    前面介绍了如何熟悉和使用Labview自带的库函数以及调试方式,大家后期基本可以凭借这两个方式从入门到出家了,哈哈,后面就靠各位同仁99%的努力了.这篇为啥要讲移位寄存器呢,主要是之前做的项目和经验告 ...

  10. 牛客SQL刷题第三趴——SQL必知必会

    01检索数据 SQL60 从 Customers 表中检索所有的 ID 编写 SQL 语句,从 Customers 表中检索所有的cust_id select * from Customers; SQ ...