【uoj#315/bzoj4943】[NOI2017]蚯蚓排队 Hash
给出 $n$ 个字符,初始每个字符单独成字符串。支持 $m$ 次操作,每次为一下三种之一:
- $1\ i\ j$ :将以 $i$ 结尾的串和以 $j$ 开头的串连到一起。
- $2\ i$ :将 $i$ 所在串从 $i$ 位置和 $i$ 下一个位置之间断开。
- $3\ S\ k$ :对于字符串 $S$ 每个长度为 $k$ 的子串,统计它在这 $n$ 个字符组成所有字符串中出现的次数,求所有统计结果的乘积模 $998244353$ 的结果。
$n\le 2\times 10^5$ ,$m\e5\times 10^5$ ,$\sum|S|\le 10^7$ ,$k\le 50$ ,$2$ 操作次数不超过 $1000$ ,字符集大小为 $'1'\sim '6'$ 。
题解
Hash
一个显而易见的做法是:维护所有这 $n$ 个字符组成的长度在 $1\sim 50$ 之间的字符串的Hash值,查询时直接统计Hash值出现次数即可。
这样做的时间复杂度是什么呢?
看起来有 $m$ 次合并,是 $mk^2$ 的。
实则不然,当没有 $2$ 操作时,最终得到的只有 $nk$ 个子串,因此上界严格时复杂度就是 $O(nk)$ 的。而 $2$ 操作只有 $1000$ 次,每次会产生 $k^2$ 的势能贡献,这一部分也只有 $O(ck^2)$ 。
使用自然溢出Hash (范围是 $2^{64}=1.8\times 10^{19}$ ) ,再映射到大小为 $10233333$ 的哈希表上即可通过。
时间复杂度 $O(nk+ck^2+\sum|S|)$ 。
考场上想出正解,结果由于使用map只得到52分...
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
struct hashmap
{
int head[10233333] , len[20000010] , cnt[20000010] , next[20000010] , tot;
ull val[20000010];
inline void insert(int l , ull v)
{
int x = v % 10233333 , i , last = 0;
for(i = head[x] ; i ; last = i , i = next[i])
if(len[i] == l && val[i] == v)
break;
if(i) cnt[i] ++ ;
else
{
if(!last) head[x] = ++tot;
else next[last] = ++tot;
len[tot] = l , val[tot] = v , cnt[tot] ++ ;
}
}
inline void erase(int l , ull v)
{
int x = v % 10233333 , i;
for(i = head[x] ; i ; i = next[i])
if(len[i] == l && val[i] == v)
cnt[i] -- ;
}
inline int find(int l , ull v)
{
int x = v % 10233333 , i;
for(i = head[x] ; i ; i = next[i])
if(len[i] == l && val[i] == v)
return cnt[i];
return 0;
}
}mp;
int a[200010] , last[200010] , next[200010];
ull base[55];
char str[10000010];
int main()
{
int n , m , i , j , p , q , opt , x , y;
ull vx , vy , ans;
scanf("%d%d" , &n , &m);
base[0] = 1;
for(i = 1 ; i < 50 ; i ++ ) base[i] = base[i - 1] * 233;
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , mp.insert(1 , a[i] ^ '0');
while(m -- )
{
scanf("%d" , &opt);
if(opt == 1)
{
scanf("%d%d" , &x , &y) , next[x] = y , last[y] = x , vx = 0;
for(i = 1 , p = x ; i < 50 && p ; i ++ , p = last[p])
{
vx += (a[p] ^ '0') * base[i - 1] , vy = 0;
for(j = 1 , q = y ; i + j <= 50 && q ; j ++ , q = next[q])
vy = vy * 233 + (a[q] ^ '0') , mp.insert(i + j , vx * base[j] + vy);
}
}
else if(opt == 2)
{
scanf("%d" , &x) , y = next[x] , next[x] = last[y] = 0 , vx = 0;
for(i = 1 , p = x ; i < 50 && p ; i ++ , p = last[p])
{
vx += (a[p] ^ '0') * base[i - 1] , vy = 0;
for(j = 1 , q = y ; i + j <= 50 && q ; j ++ , q = next[q])
vy = vy * 233 + (a[q] ^ '0') , mp.erase(i + j , vx * base[j] + vy);
}
}
else
{
scanf("%s%d" , str + 1 , &x) , vx = 0 , ans = 1;
for(i = 1 ; i < x ; i ++ ) vx = vx * 233 + str[i];
for(i = x ; str[i] ; i ++ ) vx = vx * 233 + str[i] , ans = ans * mp.find(x , vx) % 998244353 , vx -= str[i - x + 1] * base[x - 1];
printf("%llu\n" , ans);
}
}
return 0;
}
【uoj#315/bzoj4943】[NOI2017]蚯蚓排队 Hash的更多相关文章
- [Bzoj4943][Noi2017]蚯蚓(hash)
4943: [Noi2017]蚯蚓 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 237 Solved: 110[Submit][Status][D ...
- BZOJ4943 NOI2017蚯蚓排队(哈希+链表)
能看懂题就能想到正解.维护所有长度不超过k的数字串的哈希值即可,用链表维护一下蚯蚓间连接情况.由于这样的数字串至多只有nk个,计算哈希值的总复杂度为O(nk),而分裂的复杂度为O(ck^2),询问复杂 ...
- [NOI2017]蚯蚓排队 hash
题面:洛谷 题解: 我们暴力维护当前所有队伍内的所有子串(长度k = 1 ~ 50)的出现次数. 把每个子串都用一个hash值来表示,每次改变队伍形态都用双向链表维护,并暴力更新出现次数. 现在考虑复 ...
- bzoj4943 [Noi2017]蚯蚓排队
题面:http://www.lydsy.com/JudgeOnline/upload/Noi2017D1.pdf 正解:字符串$hash$. 我在考场上写了个$map$的$hash$被卡成$40$分, ...
- BZOJ4943 & 洛谷3823 & UOJ315:[NOI2017]蚯蚓排队——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4943 http://uoj.ac/problem/315 https://www.luogu.or ...
- 洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】
题目链接 洛谷P3832 题解 字符串哈希然后丢到hash表里边查询即可 因为\(k \le 50\),1.2操作就暴力维护一下 经复杂度分析会发现直接这样暴力维护是对的 一开始自然溢出WA了,还以为 ...
- [NOI2017]蚯蚓排队(链表+hash)
这题看题面感觉挺玄学的,但其实会挂链式hash就能暴力切了,就是纸老虎,考察选手的语文水平.不过三年没写挂链hash也应该写一下了…… 首先模数设成自然溢出ull,然后挂链时的模数取2^24.然后就可 ...
- BZOJ4943 [NOI2017] 蚯蚓
题目描述 蚯蚓幼儿园有nn 只蚯蚓.幼儿园园长神刀手为了管理方便,时常让这些蚯蚓们列队表演. 所有蚯蚓用从11 到nn 的连续正整数编号.每只蚯蚓的长度可以用一个正整数表示,根据入园要求,所有蚯蚓的长 ...
- P3823_[NOI2017]蚯蚓排队 哈希+脑子
之前就写过一遍,今天却写挂了,查了半天发现是数组名写错啦$qwq$ 观察到$K$很小,所以使得我们可以哈希(怎么什么都能哈希$qwq$).我们把长度小于等于$50$的子串扔到哈希表里,并统计出现次数, ...
随机推荐
- 「专题训练」Collecting Bugs(POJ-2096)
题意与分析 题意大致是这样的:给定一个\(n\times s\)的矩阵,每次可以随机的在这个矩阵内给一个格子染色(染过色的仍然可能被选中),问每一行和每一列都有格子被染色的次数的期望. 这题如果从概率 ...
- flask中的简单的前端写入
那么flask这个框架是web开发,那么肯定离不开前端的一些代码,那么python用的web开发框架 开发所用的前端模板就是jinja2模板.相对于jinja1比起来性能做到了很大的提升,那么Vue一 ...
- Gitlab 403 forbidden 并发引起IP被封
问题 在工作中自搭建的Gitlab.但今天打开页面的时候显示的是空白页面,上面还有一次文本Forbidden. 原因 Gitlab使用rack_attack做了并发访问的限制. 解决方案 将Gitla ...
- iFIERO - (一) 宇宙大战 SPACE BATTLE — 场景SCENE、SpriteKit精灵、PARTICLE粒子及背景音乐
开始游戏教程前,首先介绍一下SpriteKit是什么?SpriteKit提供了一个图形渲染和动画的基础结构,你可以使用它让任意类型的纹理图片或者精灵动起来.SpriteKit使用渲染循环,利用图形硬件 ...
- MYSQL数据库与Emoji表情的故事
问题背景 手机上众多输入法和键盘支持输入 emoji 表情,给早期设计的程序造成了越来越多的干扰. 移动端购物的流行,2018 年 "双十一"全网移动端交易达到 93.6% 微信年 ...
- 学习笔记 | Set
目录 Set Set 前言 不会数据结构选手 当几乎没写过什么数据结构的菜鸡遇上了毒瘤的splay和treap 时间正一点一点地被续走TAT 听说set有时候可以替代treap和splay 那么菜鸡L ...
- Sony深度学习框架 - Neural Network Console - 教程(1)- 原来深度学习可以如此简单
“什么情况!?居然不是黑色背景+白色文字的命令行.对,今天要介绍的是一个拥有白嫩的用户界面的深度学习框架.” 人工智能.神经网络.深度学习,这些概念近年已经涌入每个人的生活中,我想很多人早就按捺不住想 ...
- 利用Elasticsearch搭建全球域名解析记录
前言 数据来源,由Rapid7收集并提供下载https://scans.io/study/sonar.fdns 下载Elasticsearch 2.3 ElasticSearch是一个基于Lucene ...
- 移动设备检测类Mobile_Detect.php
移动设备检测类Mobile_Detect.php http://mobiledetect.net/ 分类:PHP 时间:2015年11月28日 Mobile_Detect.php是一个轻量级的开源移动 ...
- JavaWeb项目通过调用cmd实现备份数据库的功能
1.别急着上车,先测试一下能否成功调用cmd,可以尝试通过cmd命令打开计算器,代码如下: 2.能成功打开计算器后,证明调用cmd的方法是没错的,现在把cmd命令字符串改成我们备份数据库的 命 ...