洛谷P3167 通配符匹配 [CQOI2014] 字符串
正解:哈希+dp/AC自动机/kmp
解题报告:
这题解法挺多的,所以就分别港下好了QwQ
首先港下hash+dp趴
可以考虑设dp式f[i][j]:匹配到第i个通配符了,下面那个字符串匹配到第j位了是否可行
转移的话就只要关心两个通配符之间的那一段是否相等就好
那判断相等就应该要想到哈希鸭,就做完了
啊有点儿简洁,,,
思路挺简单的主要细节比较多趴,所以我等下直接放代码好了QwQ
然后说下AC自动机
就先按'*'通配符分成几段,然后对每段独立地分别做
然后下面当每段之间相对独立,说下每段内部怎么做
首先在每段内部,按'?'再分成几段,分别插入AC自动机中,建fail指针balabala不讲
然后就直接把整个儿下面的那个串在AC自动机上跑,然后开个数组cnt[]记录原串上的每个节点作为开头能匹配上这一段的多少个小段
然后再遍历一遍这整个儿串判断下,如果cnt==小段的数量就欧克了
然后这儿注意下,就因为它每次都直接整个儿原串上跑一次,所以还要记录一下上一次在原串上匹配到第几位了,强制在这一位之后匹配
两个小细节注意下
第一个是这个其实用了一个贪心的小思想,即尽量在前面匹配,可以证明这显然是对的,懒得证了挺显然的还QwQ
第二个是特判下开头结尾有没有'*',特殊处理下
还有一个不算细节问题,,,只是随手记下QAQ就开AC自动机本来是互相独立的嘛,但是如果每次重新建就要先清空再balabala的,就很麻烦,所以直接新开一个根节点然后一直接着做就好,overr(好像没有表述好,,,直接看我代码趴QAQ
(打完代码的lq又回来补充了,,,还有一个细节就,我开始打都快打完了,突然脑子一抽,就觉得,好像可以直接开struct{}tr[N],这样分别表示每个AC自动机代码打起来就很简单
然后我就全删了,改改改改
改完之后我突然意识到有个问题,,,就我是写的数组型,然后我并不知道每个串长的上界,只知道所有串长的上界,内存就会爆炸,所以提醒一下不要这么写,,,当然如果你是指针玩家当然麻油关系QAQ
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define ri register int
#define rb register bool
#define rc register char
#define ll unsigned long long
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)
+;
char ch[N],s[N];
int nod_cnt,cnt[N],n,rt[N],num,str_cnt[N],lst,lin_cnt;
bool bg,ls;
struct node
{
],fail;}tr[N];vector<int>ed[N];queue<int>Q;
il void insert(ri l,ri r,ri id,ri num)
{
ri nw=rt[num];
rp(i,l,r)
{
])tr[nw].to[s[i]-]=++nod_cnt;
nw=tr[nw].to[s[i]-];
}
ed[nw].push_back(id);
}
il void get_fail(ri num)
{
rp(i,,)if(tr[rt[num]].to[i])Q.push(tr[rt[num]].to[i]),tr[tr[rt[num]].to[i]].fail=rt[num];else tr[rt[num]].to[i]=rt[num];//,printf("to=%d\n",tr[rt[num]].to[i]);
while(!Q.empty())
{
ri nw=Q.front(),sz=ed[tr[nw].fail].size();Q.pop();
rp(i,,sz-)ed[nw].push_back(ed[tr[nw].fail][i]);
rp(i,,)
if(tr[nw].to[i])Q.push(tr[nw].to[i]),tr[tr[nw].to[i]].fail=tr[tr[nw].fail].to[i];
else tr[nw].to[i]=tr[tr[nw].fail].to[i];//,printf("to=%d\n",tr[nw].to[i]);
}
}
il void bd(ri l,ri r,ri num)
{
rt[num]=++nod_cnt;
for(ri i=l;i<=r;++i)
if(s[i]!='?')
{
ri pos=i;
while(pos<=r && s[pos]!='?')++pos;
--pos;
insert(i,pos,pos-l+,num);
++str_cnt[num];
i=pos;
}
get_fail(num);
}
il bool fd(ri num,ri l,ri r,rb fr,rb nd)
{
ri nw=rt[num];memset(cnt,,sizeof(cnt));
rp(i,,n)
{
nw=tr[nw].to[ch[i]-];ri sz=ed[nw].size();
rp(j,,sz-){)++cnt[i-ed[nw][j]+];}
}
rp(i,lst+,n)
{
if(cnt[i]==str_cnt[num])
{
)
{
)continue;
if(nd && !ls && i+r-l!=n)continue;
// printf("%d\n",lst);
lst=i+r-l;;
}
if(nd && !ls && i+r-l!=n)continue;
// printf("%d\n",lst);
lst=i+r-l;;
}
}
;
}
}tr;
il int read()
{
rc ch=gc;ri x=;rb y=;
'))ch=gc;
;
)+(x<<)+(ch^'),ch=gc;
return y?x:-x;
}
int main()
{
// freopen("3167.in","r",stdin);//freopen("3167.out","w",stdout);
scanf();ri lth=strlen(s+);bg=s[]=='*';ls=s[lth]=='*';while(lth && s[lth]=='*')--lth;
;i<=lth;++i)if(s[i]!='*'){ri pos=i;while(s[pos]!='*' && pos<=lth)++pos;--pos;tr.bd(i,pos,++lin_cnt);i=pos;}
ri T=read();
while(T--)
{
scanf();n=strlen(ch+);if(!lth){printf("YES\n");continue;}
lin_cnt=;rb flg=;lst=;
;i<=lth;++i)
if(s[i]!='*')
{
ri pos=i;while(s[pos]!='*' && pos<=lth)++pos;++lin_cnt;--pos;
;break;}
i=pos;
}
flg?printf("NO\n"):printf("YES\n");
}
;
}
kmp我麻油get,,,但是听说和AC自动机很像,,,?所以我先把前两个的代码打了然后可能明天或者以后想起来了再想下kmp怎么做,,,想起来了就写想不出来就当没有kmp这个算法TT
洛谷P3167 通配符匹配 [CQOI2014] 字符串的更多相关文章
- 洛谷 P3370 【模板】字符串哈希
洛谷 P3370 [模板]字符串哈希 题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的 ...
- 【洛谷P3709】大爷的字符串题
看这题网上居然还没人写blog,怕是都去看洛谷自带的了-- 你才是字符串!你全家都是字符串!这题跟字符串没多大关系,只是出题人lxl想要吐槽某中学而已--... 其实这题说白了就是问区间里出现最多的数 ...
- 【洛谷4173】残缺的字符串(重拾FFT)
点此看题面 大致题意: 有一个长度为\(n\)的字符串\(A\)和一个长度为\(m\)的字符串\(B\),其中存在一些字符'*'可以与任意字符匹配.求\(B\)中所有满足条件的位置,使得从这一位置开始 ...
- 【洛谷P4173】残缺的字符串
题目大意:给定一个文本串和一个模板串,串中含有通配符,求文本串中有多少个位置可以与文本串完全匹配. 题解:利用卷积求解字符串匹配问题. 通配符字符串匹配的数值表示为 \[\sum\limits_{i ...
- 洛谷P3370 【模板】字符串哈希
P3370 [模板]字符串哈希 143通过 483提交 题目提供者HansBug 标签 难度普及- 提交 讨论 题解 最新讨论 看不出来,这题哪里是哈希了- 题目描述 如题,给定N个字符串(第i个 ...
- 洛谷P1140 基因匹配 //DP真正意义上的一血
题目背景 大家都知道,基因可以看作一个碱基对序列.它包含了44种核苷酸,简记作A,C,G,TA,C,G,T.生物学家正致力于寻找人类基因的功能,以利用于诊断疾病和发明药物. 在一个人类基因工作组的任务 ...
- [洛谷P4925][1007]Scarlet的字符串不可能这么可爱
题目大意:问字符集大小为$k$,长度为$L$的字符串,且没有长度超过$1$的回文段的个数.规定第$s(若为0则无限制)$位为$w$. 题解:懒得写了,根据是否有限制分类讨论 卡点:中途有个地方忘记取模 ...
- 洛谷 2543 [AHOI2004]奇怪的字符串
题目描述 输入输出格式 输入格式: 输入文件中包含两个字符串X和Y.当中两字符串非0即1.序列长度均小于9999. 输出格式: X和Y的最长公共子序列长度. 输入输出样例 输入样例#1: 010101 ...
- 洛谷—— P2543 [AHOI2004]奇怪的字符串
P2543 [AHOI2004]奇怪的字符串 题目描述 输入输出格式 输入格式: 输入文件中包含两个字符串X和Y.当中两字符串非0即1.序列长度均小于9999. 输出格式: X和Y的最长公共子序列长度 ...
随机推荐
- 详解 JVM Garbage First(G1) 垃圾收集器(转载)
前言 Garbage First(G1)是垃圾收集领域的最新成果,同时也是HotSpot在JVM上力推的垃圾收集器,并赋予取代CMS的使命.如果使用Java 8/9,那么有很大可能希望对G1收集器进行 ...
- springboot更换日志系统
背景:springboot.2.1.2默认使用logback作为日志系统,我想禁用logback,换成效率更高的log4j2. 一.去除默认的logback依赖 1. 方法一 精准去除 depende ...
- CentOS 6.5 x64下安装VMware tools
[root@CentOS6 /]# mount /dev/cdrom /mnt mount: block device /dev/sr0 is write-protected, mounting re ...
- python时间模块time详解
在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. 在开始之前,首先要说明这几点: ...
- Openfire 单人聊天和多人聊天(发送消息、接收消息)
Openfire 单人聊天和多人聊天(发送消息.接收消息) 一.单人聊天 1)发送消息: 首先要获取一个聊天窗口,getConnection()为获取连接connection的方法,调用getFrie ...
- Jupyter/JupyterLab安装使用
一.介绍 Jupyther notebook(曾经的Ipython notebook),是一个可以把代码.图像.注释.公式和作图集于一处,实现可读性及可视化分析的工具,支持多种编程语言.官方使用手册. ...
- windows上RSA密钥生成和使用
一,下载安装windows平台openssl密钥生成工具,执行安装目录bin下的"openssl.exe",执行后弹出命令窗口如下 运行 二,生成私钥 输入"genrsa ...
- Android开发怎么让自己的APP UI漂亮、大方(规范篇一)
首先,笔者是站立在开发者的角度来看UI设计的,欢迎专业人士提供指导,不多说,来看怎么把UI设计和开发高效结合起来~ 一.约定APP开发中的一些规则 1.大部分图标满足HDPI(高清)即可,比如:大众点 ...
- python 解除装饰器,调用原本函数。
假设fun函数被装饰器装饰了,name调用fun,就不是调用fun本身了,那么如何继续调用本身呢.使用fun_raw = fun.__wrapped__这样使用fun_raw就是调用没被装饰器修饰后的 ...
- linux内存和swap
https://www.cnblogs.com/Zfc-Cjk/archive/2018/02/13/8447270.html