「题解报告」 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. 测试平台系列(97) 完善执行case部分

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节我们讨论了怎么结束一个 ...

  2. PHP时间轴函数

    PHP时间轴函数可以更好的去进行用户体验.让用户动态的知道最近是什么时候,而不是死板的datatime去转换成固定的时间. 后续版本会考虑添加这个功能,代码先贴出来. function tranTim ...

  3. 为什么要使用TypeScript(Why Typescript?)

    客观原因 静态类型. 在编译期即可进行静态类型分析, 减少JS运行时类型错误. 语法功能强大 对于大型项目具有更好构建机制,加入了类.接口.泛型.模块等概念. 兼容JavaScript 与现存的Jav ...

  4. C# 将HTML转为XML

    本文以C#及VB.NET后端程序代码示例展示如何将HTML转为XML文件.转换时,调用Word API -Free Spire.Doc for .NET 提供的文档加载方法及文档保存的方法来实现.转换 ...

  5. Python自动化办公:27行代码实现将多个Excel表格内容批量汇总合并到一个表格

    序言 (https://jq.qq.com/?_wv=1027&k=GmeRhIX0) 老板最近越来越过分了,快下班了发给我几百个表格让我把内容合并到一个表格内去.还好我会Python,分分钟 ...

  6. idea部署项目运行没问题,但是页面404。

    解决方案: 这个位置不要添加内容. 参考:https://blog.csdn.net/hupixiong/article/details/105443606

  7. 【转载】vscode配置C/C++环境

    VScode中配置 C/C++ 环境 Tip:请在电脑端查看 @零流@火星动力猿 2022.4.12 1. 下载编辑器VScode 官网:https://code.visualstudio.com/( ...

  8. (零)机器学习入门与经典算法之numpy的基本操作

    1.根据索引来获取元素* 创建一个索引列表ind,用来装载索引,当numpy数据是一维数据时:一个索引对应的是一个元素具体的例子如下: import numpy as np # 数据是一维数据时:索引 ...

  9. C++ 加速(卡常)技巧【超级 快读、快写】

    C++ \texttt{C++} C++ 加速技巧 快读快写 快读 inline int read() { int x = 0, w = 0; char ch = 0; while (!isdigit ...

  10. el-form 每行显示两列,底部按钮居中

    需求: el-form 每行显示两列,底部按钮居中 问题: 以前的解决办法是: el-col, el-row.但是这里只有一个 el-form-item 的 label 数据是已知的,其余项都是循环得 ...