BZOJ3574 HNOI2014抄卡组(哈希)
容易发现通配符中间的部分可以任意匹配,会造成的无法匹配的仅仅是前后缀,前缀和后缀可以分别独立处理。如果字符串均有通配符,只需要按前/后缀长度排序然后暴力匹配就可以了。
问题在于存在无通配符的字符串。显然首先这些字符串需要相同。剩下的字符串只要都能与该字符串匹配即可。然后就不会了。想了半天去看题解……暴力哈希。为啥跑2e8这么自信啊。
bzoj莫名T。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 100010
#define L 10000010
#define ul unsigned long long
int T,n,pre[N],suf[N],id[N];
ul hash[][L],p[L];
vector<char> s[N];
bool isac(char c){return c>='a'&&c<='z'||c>=''&&c<=''||c=='*';}
bool cmp(const int&a,const int&b)
{
return pre[a]<pre[b];
}
bool check(int n)
{
for (int i=;i<=n;i++) id[i]=i;
sort(id+,id+n+,cmp);
for (int i=;i<=n;i++)
for (int j=;j<pre[id[i-]];j++)
if (s[id[i-]][j]!=s[id[i]][j]) return ;
return ;
}
ul gethash(int k,int l,int r)
{
if (l>r) return ;
return hash[k][r]-hash[k][l-]*p[r-l+];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj3574.in","r",stdin);
freopen("bzoj3574.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
T=read();
p[]=;for (int i=;i<=L-;i++) p[i]=p[i-]*;
while (T--)
{
n=read();
for (int i=;i<=n;i++)
{
s[i].clear();
char c=getchar();while (!isac(c)) c=getchar();
while (isac(c)) s[i].push_back(c),c=getchar();
}
hash[][]=;int len=;bool flag=;
for (int i=;i<=n;i++)
{
int l=s[i].size();
pre[i]=l,suf[i]=-;
for (int j=;j<l;j++)
if (s[i][j]=='*') {pre[i]=j;break;}
for (int j=l-;~j;j--)
if (s[i][j]=='*') {suf[i]=j;break;}
if (pre[i]==l)
if (!len)
{
len=l;
for (int j=;j<l;j++) hash[][j+]=hash[][j]*+s[i][j];
}
else
{
ul tot=;
for (int j=;j<l;j++) tot=tot*+s[i][j];
if (tot!=hash[][len]) {flag=;break;}
}
}
if (!flag) {cout<<"N\n";continue;}
if (!len)
{
if (!check(n)) {cout<<"N\n";continue;}
for (int i=;i<=n;i++)
{
reverse(s[i].begin(),s[i].end());
pre[i]=(int)s[i].size()-suf[i]-;
}
if (!check(n)) {cout<<"N\n";continue;}
cout<<"Y\n";
}
else
{
bool flag=;
for (int i=;i<=n;i++)
if (pre[i]!=s[i].size())
{
hash[][]=;
int l=s[i].size();
for (int j=;j<l;j++) hash[][j+]=hash[][j]*+s[i][j];
if (pre[i]+l--suf[i]>len||gethash(,,pre[i])!=gethash(,,pre[i])||gethash(,len-l+suf[i]+,len)!=gethash(,suf[i]+,l)) {flag=;break;}
int x=pre[i]+;flag=;
for (int j=pre[i];j<=suf[i];j++)
{
if (j==suf[i]) flag=;
if (s[i][j]=='*') continue;
int t=j;
while (s[i][t+]!='*') t++;
while (x+t-j<len-l+suf[i]+&&gethash(,x,x+t-j)!=gethash(,j+,t+)) x++;
if (x+t-j>=len-l+suf[i]+) break;
j=t;
}
if (flag) break;
}
if (flag) cout<<"N\n";else cout<<"Y\n";
}
}
return ;
}
BZOJ3574 HNOI2014抄卡组(哈希)的更多相关文章
- bzoj3574[Hnoi2014]抄卡组
http://www.lydsy.com/JudgeOnline/problem.php?id=3574 我们发现如果所有的字符串都有*,那么只需要比较他们的“前缀”和“后缀”相同即可.“前缀”指第一 ...
- 【LG3234】[HNOI2014]抄卡组
题面 题解 分三种情况: 若所有串都没有通配符,直接哈希比较即可. 若所有串都有通配符, 把无通配符的前缀 和 无通配符的后缀哈希后比较即可. 中间部分由于通配符的存在,一定可以使所有串匹配. 若部分 ...
- [HNOI2014]抄卡组
[Luogu3234] [LOJ2208] 题解及代码 锻炼哈希码力的一道题 , 具体细节见代码 #include<cstdio> #include<cstring> #inc ...
- luogu P3234 [HNOI2014]抄卡组
传送门 nmdwsm 自己看吧,不想写了qwq 垃圾代码如下 和题解完全不一样 #define LL long long #define uLL unsigned long long #define ...
- 洛谷P3234 抄卡组 [HNOI2014] 字符串hash
正解:字符串hash 解题报告: 传送门! 字符串hash是字符串匹配中很常见的一个方法,原理也很好懂,这里就不做太多阐述辣有时间放到hash笔记里面去QAQ 题意不说了挺好理解的,自带一句话概括好评 ...
- 【HNOI2014】抄卡组
题面 题解 如果所有的字符串都有通配符,那么只要比较不含通配符的前缀和后缀就可以了. 否则一定有一个串没有通配符.找出这个字符串,然后将所有串与这个串匹配,通配符将\(B\)分成一段一段在\(A\)上 ...
- 【LOJ6254】最优卡组 堆(模拟搜索)
[LOJ6254]最优卡组 题面 题解:常用的用堆模拟搜索套路(当然也可以二分).先将每个卡包里的卡从大到小排序,然后将所有卡包按(最大值-次大值)从小到大排序,并提前处理掉只有一张卡的卡包. 我们将 ...
- HearthBuddy卡组
偶数萨 手打两天已上传说,各位加油 欧洲牧羊人 ### 火元素换艾雅# 职业:萨满祭司# 模式:狂野模式## 2x (2) 图腾魔像 # 2x (2) 大漩涡传送门 # 2x (2 ...
- 服务器&阵列卡&组raid 5
清除raid信息后,机器将会读不到系统, 后面若进一步操作处理, raid信息有可能会被初始化掉,那么硬盘数据就有可能会被清空, 导致数据丢失, 否则如果只是清除raid信息,重做raid是可以还原系 ...
随机推荐
- WEB项目日志分析系统思考
一.为什么需要日志分析系统 对ETL系统中数据转换和存储操作的相关日志进行记录以及实时分析有助于我们更好的观察和监控ETL系统的相关指标(如单位时间某些操作的处理时间),发现系统中出现的缺陷和性能瓶颈 ...
- windows下安装,配置redis以及可视化客户端redisClient的安装及基本使用
一. Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你系统平台的实际情 ...
- UTC时间转为正常日期
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);SimpleDa ...
- python与其他语言的区别
C 和 Python.Java.C#等 C语言: 代码编译得到 机器码 ,机器码在处理器上直接执行,每一条指令控制CPU工作 其他语言: 代码编译得到 字节码 ,虚拟机执行字节码并转换成机器码再后在处 ...
- Eclipse 使用过程中的问题及解决方法
1.Eclipse中java文件和jsp字体大小设置 1.更改所有文件的字体显示大小过程: Window->preferences->General->Appearance-> ...
- QML和JS引擎的关系以及调用c++函数的原理
首先推荐几篇博客 1.深入解析QML引擎, 第1部分:QML文件加载 https://www.cnblogs.com/wzxNote/p/10569535.html 2.深入解析QML引擎, 第2部分 ...
- python爬虫-爬取盗墓笔记
本来今天要继续更新 scrapy爬取美女图片 系列文章,可是发现使用免费的代理ip都非常不稳定,有时候连接上,有时候连接不上,所以我想找到稳定的代理ip,下次再更新 scrapy爬取美女图片之应对反 ...
- 四、利用EnterpriseFrameWork快速开发基于WCF为中间件的三层结构系统
回<[开源]EnterpriseFrameWork框架系列文章索引> EnterpriseFrameWork框架实例源代码下载: 实例下载 本章内容与上一张<利用Enterprise ...
- POJ 3278 Catch That Cow (附有Runtime Error和Wrong Answer的常见原因)
题目链接:http://poj.org/problem?id=3278 Catch That Cow Time Limit: 2000MS Memory Limit: 65536K Total S ...
- 智慧树mooc自动刷课代码
最近学习javaScript和JQuery,恰好还有一门mooc没有看.结合学习的知识和其他人的代码:撸了一个自动播放课程的代码,同时自动跳过单章的测试题. 用电脑挂着不动就完事了. 如下: var ...