「题解报告」 P3167 [CQOI2014]通配符匹配
「题解报告」 P3167 [CQOI2014]通配符匹配
思路
*和?显然无法直接匹配,但是可以发现「通配符个数不超过 \(10\) 」,那么我们可以考虑分段匹配。
我们首先把原字符串分成多个以一个通配符开头的字符串,如将 happy*birthdey?xingchen 分成:
happy
*birthday
?xingchen
然后设原串有 \(m\) 个通配符, \(op_i\) 表示分出来的第 \(i\) 个串前的通配符(\(0\) 没有,\(1\) 是?,\(2\) 是*),\(len_i\) 表示分出来的第 \(i\) 个串的长度,\(f_{i,j}\) 表示分出来的第 \(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]通配符匹配的更多相关文章
- P3167 [CQOI2014]通配符匹配 题解
题目 题目大意 给出一个字符串,其中包含两种通配符 ‘?’和 ‘*’ ,‘?’可以代替一个字符,‘*’可以代替一个字符串(长度可以为0) 然后给出几个字符转,判断能否用给出的字符串表示出来 样例解释 ...
- 「题解报告」P4577 [FJOI2018]领导集团问题
题解 P4577 [FJOI2018]领导集团问题 题解区好像没有线段树上又套了二分的做法,于是就有了这片题解. 题目传送门 怀着必 WA 的决心交了两发,一不小心就过了. 题意 求一个树上最长不下降 ...
- 「题解报告」P2154 虔诚的墓主人
P2154 虔诚的墓主人 题解 原题传送门 题意 在 \(n\times m\) 一个方格上给你 \(w\) 个点,求方格里每个点正上下左右各选 \(k\) 个点的方案数. \(1 \le N, M ...
- 「题解报告」SP16185 Mining your own business
题解 SP16185 Mining your own business 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...
- 「题解报告」Blocks
P3503 Blocks 题解 原题传送门 思路 首先我们可以发现,若 \(a_l\) ~ \(a_r\) 的平均值大于等于 \(k\) ,则这个区间一定可以转化为都大于等于 \(k\) 的.我们就把 ...
- 「题解报告」P3354
P3354 题解 题目传送门 一道很恶心的树形dp 但是我喜欢 题目大意: 一片海旁边有一条树状的河,入海口有一个大伐木场,每条河的分叉处都有村庄.建了伐木场的村庄可以直接处理木料,否则要往下游的伐木 ...
- 「题解报告」CF1067A Array Without Local Maximums
大佬们的题解都太深奥了,直接把转移方程放出来让其他大佬们感性理解,蒟蒻们很难理解,所以我就写了一篇让像我一样的蒟蒻能看懂的题解 原题传送门 动态规划三部曲:确定状态,转移方程,初始状态和答案. --神 ...
- P3167 [CQOI2014]通配符匹配
吐槽 本来是去写AC自动机的,然后发现数据范围每个串100000,有100个串(???),连塞进trie树里都塞不进去,玩个鬼的AC自动机啊,tag不要乱打啊 最后拿字符串hash+爆搜一发搜过去了. ...
- 「题解报告」P7301 【[USACO21JAN] Spaced Out S】
原题传送门 神奇的5分算法:直接输出样例. 20分算法 直接把每个点是否有牛的状态DFS一遍同时判断是否合法,时间复杂度约为\(O(2^{n^2})\)(因为有判断合法的剪枝所以会比这个低).而在前四 ...
随机推荐
- 【Redis】Redis Cluster初始化及PING消息的发送
Cluster消息类型定义 #define CLUSTERMSG_TYPE_PING 0 /* Ping消息类型,节点间进行通信交换信息的消息 */ #define CLUSTERMSG_TYPE_P ...
- BUUCTF-刷新过的图片
刷新过的图片 刷新在MISC中比较特殊,一般是指F5隐写方式 直接使用工具提取出来,发现生成的是Pk开头的,应该是zip格式 使用16进制确认了是ZIP,将生成的output.txt改为output. ...
- SAP Web Dynpro-监视应用程序
您可以使用ABAP监视器来监视Web Dynpro应用程序. 存储有关Web Dynpro应用程序的信息. 您可以使用T代码-RZ20查看此信息. 您可以在Web Dynpro ABAP监视器中查看以 ...
- kali 无线网络渗透测试
一.无线网络渗透嗅探工具Kismet 如果要进行无线网络渗透测试,则必须先扫描所有有效的无线接入点.在Kali linux中,提供了一款嗅探无线网络工具Kismet.使用该工具可以测量周围的无线信号, ...
- ansible变量引用
1. 在/etc/ansible/hosts默认文件中定义变量 [test] 192.168.163.130 #[test:vars] #key=ansible 或者 192.168.163.130 ...
- resultMap自定义映射(多对一)
自定义resultMap,处理复杂的表关系,实现高级结果集映射 1) id :用于完成主键值的映射 2) result :用于完成普通列的映射 3) association :一个复杂的类型关联;许多 ...
- git的工作原理和git项目创建及克隆
Git基本理论(重要)三个区域Git本地有三个工作区域:工作目录(Working Directory).暂存区(Stage/Index).资源库(Repository或Git Directory).如 ...
- jdk8 hashmap 链表resize 源码分析
重点看这部分代码 for (int j = 0; j < oldCap; ++j) { Node<K,V> e; if ((e = oldTab[j]) != null) { old ...
- 面试突击64:了解 HTTP 协议吗?
HTTP(Hyper Text Transfer Protocol)超文本传输协议,下文简称 HTTP,它的作用是用于实现服务器端和客户端的数据传输的.它可以传输任意的数据类型,如文本.HTML.图片 ...
- CTO与CIO选型数据中台的几大建议
企业数字化转型离不开企业数字化技术的配备.但企业在选择数字化技术时也面临着一个问题,就是如何在大胆采用先进的数字化技术和对技术进行投资之间找到平衡,将投资风险降到最低,毕竟错误的技术选型会给企业带来不 ...