洛谷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的最长公共子序列长度 ...
随机推荐
- utf-8 编码问题
使用下面直接进行处理$str = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $str);
- kubernetes 学习资料
谷歌大神详解 Kubernetes 配置管理最佳方法 https://www.kubernetes.org.cn/3031.html all in on kubernetes https://gith ...
- Fluent动网格【13】:网格光顺总结及实例
光顺(Smoothing)方法是最基本的网格节点更新方法.Fluent提供了三种光顺方法: Spring弹簧光顺 Diffusion扩散光顺 Linearly Elastic Solid光顺 三种方法 ...
- 一分钟内搭建全web的API接口神器json-server详解
JSON-Server 是一个 Node 模块,运行 Express 服务器,你可以指定一个 json 文件作为 api 的数据源. 安装json-server npm install -g json ...
- python3 log 日志记录
在调试的过程中,很多地方需要用到日志 如下 import logging LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s&qu ...
- Ubuntu16.04下搭建Go语言环境
1. 安装GO sudo apt-get install golang-go 2. 设置Go环境变量 打开终端,输入命令: export GOROOT=$HOME/goexport PATH=$GOR ...
- Sword libcurl回调函数相关知识
libcurl响应回调函数说明 libcurl在默认情况下,回调里面会将数据分段的返回,不会一下子将发送端的数据全部塞到回调函数里面, 经过源码分析回调函数和curl_easy_perform是在 ...
- yii2快速導出phpexcel
https://packagist.org/packages/moonlandsoft/yii2-phpexcel 安装方式:首先是已经安装过Composer,则通过 Composer 下载安装 Mo ...
- xxl-job安装教程
xxl-job是一个开源的分布式调度框架,其他类似的框架还有airflow,oozie等等,需要进行对比 https://github.com/xuxueli/xxl-job 1.首先git clon ...
- dhcpsrv:windows系统的优秀开源免费dhcp serve软件
概述: 官方网站 :http://www.dhcpserver.de/ 写博客时的可免费下载版本 2.52, 或者在cnblogs 本地下载 --========================== ...