洛谷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的最长公共子序列长度 ...
随机推荐
- 【C#】解析C#中管道流的使用
目录结构: contents structure [+] 匿名管道(anonymous pipe) 命名管道(named pipe) 管道为进程间通信提供了一种可能.管道分为两种,一种是匿名管道,另一 ...
- Linux下逻辑地址、线性地址、物理地址详细总结
Linux下逻辑地址.线性地址.物理地址详细总结 一.逻辑地址转线性地址 机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址 ...
- Effective Java 第三版——75. 在详细信息中包含失败捕获信息
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- Effective Java 第三版——73.抛出合乎于抽象的异常
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- 深入 AngularUI Router
翻译:深入 AngularUI Router 原文地址:http://www.ng-newsletter.com/posts/angular-ui-router.html ui-router: htt ...
- idea 自动导入
- 大数据:Hive - ORC 文件存储格式
一.ORC File文件结构 ORC的全称是(Optimized Row Columnar),ORC文件格式是一种Hadoop生态圈中的列式存储格式,它的产生早在2013年初,最初产生自Apache ...
- Python中的三元运算符
Python中的三元运算符 对于如下需求: if var1>1 : goal = "执行表达式1" else: goal = "执行表达式2" 1.在其他 ...
- 使用winsw部署spring boot jar 项目
参考:用winsw让任何Windows程序都能运行为服务 简介在linux下部署springboot项目是一件很简单的事,直接后台运行就行了,最多写个shell脚本开机自启就行了.我们最近做的项目需要 ...
- 删除SQL架构的用户
ALTER AUTHORIZATION ON SCHEMA::db_owner TO db_owner