UCloud 的安全秘钥

题意

给出一个数组 s 串,和数组 t 串,那么如果两者长度相同且两者所含的数字全部相同,则说这两个串相似。

给定原始串 S ,以及 m 个询问 T 串,问 S 串有多少个连续子串和 T 串相似。

分析

2017年计蒜之道第五场的题目。题目很有趣,虽然比赛里只水出了中等难度。看了题解,学到了新姿势!

这道题,为了优化复杂度,就是要快速判断两个数组是否完全相同,

对于中等难度,询问的次数很少,那么我们就要加快 T 和 S 的子串的比较速度,那么可以把 1到50000 (n <= 50000)分别映射到64位无符号整型数(允许自然溢出),对于查询的串,把对应的映射后的值加起来,和 S 的子串(也是映射后的)分别比较即可。复杂度 \(O(nm)\) 。

对于困难难度,询问次数1e5,但是注意到题目给出的查询的串 T 的总长度 (len) <= 2e5 ,那么最多只有 \(\sqrt{len}\) 种长度,对于每一种长度,求出 S 的所有子串,并把这些子串和查询的串全部放到一个数组里面排序,通过遍历一遍数组即可算出答案。复杂度\(O(nlogn\sqrt{len})\) 。

我把困难难度的代码再交到中等难度题目里面,发现运行时间893ms,而 \(O(nm)\) 的算法只需要66ms,因为困难难度的代码的复杂度已经和查询的次数无关了,对于不同数据,设计不同的算法,要充分利用题目给出的信息。

code (\(O(nm)\))

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 5e4 + 10;
int n, m;
int a[MAXN];
int t[MAXN];
unsigned long long Z[MAXN];
int main() {
srand(timezone);
for(int i = 0; i < MAXN; i++) {
Z[i] = (unsigned long long)rand() * rand() * rand() * rand();
}
cin >> n;
for(int i = 0; i < n; i++) {
cin >> a[i];
}
cin >> m;
while(m--) {
int k, num = 0;
cin >> k;
if(k > n) {
puts("0");
continue;
}
int cnt = 0;
unsigned long long A = 1, T = 1;
for(int i = 0; i < k; i++) {
cin >> t[i];
T += Z[t[i]];
A += Z[a[i]];
}
if(A == T) {
cnt++;
}
for(int i = k; i < n; i++) {
A -= Z[a[i - k]];
A += Z[a[i]];
if(A == T) cnt++;
}
cout << cnt << endl;
}
return 0;
}

code (\(O(nlogn\sqrt{len})\))

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int MAXN = 1e5 + 10;
int n, m;
int s[MAXN];
ull Z[MAXN];
struct A {
int id, k;
ull num;
bool operator<(const A&other) {
return k < other.k;
}
} a[MAXN];
struct node {
int q, id;
ull num;
node() {}
node(int q_, int id_, ull num_): q(q_), id(id_), num(num_) {}
bool operator<(const node&other) {
if(num != other.num) return num < other.num;
return q > other.q;
}
} d[MAXN * 2];
int ans[MAXN * 2];
int main() {
srand(timezone);
for(int i = 0; i < MAXN; i++) {
Z[i] = (ull)rand() * rand() * rand() * rand();
}
cin >> n;
for(int i = 0; i < n; i++) {
cin >> s[i];
}
cin >> m;
for(int i = 0; i < m; i++) {
cin >> a[i].k;
a[i].id = i;
for(int j = 0; j < a[i].k; j++) {
int p;
cin >> p;
a[i].num += Z[p];
}
}
sort(a, a + m);
int l = 0, r = 0;
while(r < m) {
int cnt = 0;
d[cnt++] = node(1, a[r].id, a[r].num);
while(r < m && a[r + 1].k == a[r].k) {
r++;
d[cnt++] = node(1, a[r].id, a[r].num);
}
int k = a[r].k;
if(k > n) {
ans[a[l].id] = 0;
continue;
}
ull sum = 0;
for(int i = 0; i < k; i++) {
sum += Z[s[i]];
}
if(k) d[cnt++] = node(0, 0, sum);
for(int i = k; i < n; i++) {
sum -= Z[s[i - k]];
sum += Z[s[i]];
d[cnt++] = node(0, 0, sum);
}
sort(d, d + cnt);
int l1 = 0, r1 = 0, l2 = 0, r2 = 0;
while(l1 < cnt) {
int flg = 0;
for(int i = l1; i < cnt; i++) {
if(d[i].q) {
l1 = i;
flg = 1;
break;
}
}
if(!flg) break;
r1 = l1;
while(r1 < cnt && d[r1 + 1].q && d[r1 + 1].num == d[r1].num) r1++;
int l2 = r1 + 1, r2 = l2;
if(l2 < cnt && !d[l2].q && d[l2].num == d[r1].num) {
while(r2 < cnt && !d[r2 + 1].q && d[r2 + 1].num == d[r2].num) r2++;
for(int i = l1; i <= r1; i++) {
ans[d[i].id] = r2 - l2 + 1;
}
l1 = r2 + 1;
} else l1 = r2;
}
r++;
}
for(int i = 0; i < m; i++) {
cout << ans[i] << endl;
}
return 0;
}

(计蒜客)UCloud 的安全秘钥的更多相关文章

  1. 计蒜客 UCloud 的安全秘钥(困难)(哈希)

    UCloud 的安全秘钥(困难) 编辑代码 9.53% 1200ms 262144K 每个 UCloud 用户会构造一个由数字序列组成的秘钥,用于对服务器进行各种操作.作为一家安全可信的云计算平台,秘 ...

  2. 计蒜客 UCloud 的安全秘钥(随机化+Hash)

    题目链接 UCloud 的安全秘钥 对于简单的版本,我们直接枚举每个子序列,然后sort一下判断是否完全一样即可. #include <bits/stdc++.h> using names ...

  3. 计蒜客 UCloud 的安全秘钥 ——(hash)

    题目链接:https://nanti.jisuanke.com/t/15769. 题意是求可以变换位置以后相同的子串有多少个,那么做法是只要每个数字的平方和,立方和以及四次方和都相同就可以了. 代码如 ...

  4. 计蒜课/UCloud 的安全秘钥(hash)

    题目链接:https://nanti.jisuanke.com/t/15768 题意:中文题诶- 思路:直接hash就好了,当时zz了没想到... 代码: #include <iostream& ...

  5. 计蒜客 作弊揭发者(string的应用)

    鉴于我市拥堵的交通状况,市政交管部门经过听证决定在道路两侧安置自动停车收费系统.当车辆驶入车位,系统会通过配有的摄像头拍摄车辆画面,通过识别车牌上的数字.字母序列识别车牌,通过连接车管所车辆信息数据库 ...

  6. 计蒜客的一道题dfs

    这是我无聊时在计蒜客发现的一道题. 题意: 蒜头君有一天闲来无事和小萌一起玩游戏,游戏的内容是这样的:他们不知道从哪里找到了N根不同长度的木棍, 看谁能猜出这些木棍一共能拼出多少个不同的不等边三角形. ...

  7. 计蒜客模拟赛5 D2T1 成绩统计

    又到了一年一度的新生入学季了,清华和北大的计算机系同学都参加了同一场开学考试(因为两校兄弟情谊深厚嘛,来一场联考还是很正常的). 不幸的是,正当老师要统计大家的成绩时,世界上的所有计算机全部瘫痪了. ...

  8. 计蒜客 等边三角形 dfs

    题目: https://www.jisuanke.com/course/2291/182238 思路: 1.dfs(int a,int b,int c,int index)//a,b,c三条边的边长, ...

  9. 计蒜客 方程的解数 dfs

    题目: https://www.jisuanke.com/course/2291/182237 思路: 来自:https://blog.csdn.net/qq_29980371/article/det ...

随机推荐

  1. 浩哥解析MyBatis源码(十一)——Parsing解析模块之通用标记解析器(GenericTokenParser)与标记处理器(TokenHandler)

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6724223.html 1.回顾 上面的几篇解析了类型模块,在MyBatis中类型模块包含的 ...

  2. NodeJS+express+mogondb学习笔记01

    0.准备工作  安装nodejs环境  官网地址:https://nodejs.org/en/  下载好了 直接一路安装 也没有什么可以说的 不得不说nodejs对于新手上手还是很友好的,再加上现在n ...

  3. Unity C#集合

    集合分为两种:非泛型集合,泛型集合. 非泛型集合需要引入:System.Collections命名空间,其命名空间下的类有: ArrayList表示大小根据需要动态增加的对象数组. Hashtable ...

  4. JS中的循环嵌套 BOM函数

    [嵌套循环特点]                           外层循环转一次,内层循环转一圈              外层循环控制行数,内层循环控制每行元素个数             [做 ...

  5. Andriod中自定义Dialog样式的Activity点击空白处隐藏软件盘(Dialog不消失)

    一.需求触发场景: 项目中需要出发带有EditText的Dialog显示,要求在编辑完EditText时,点击Dilog的空白处隐藏软键盘.但是Dialog不会消失.示例如下: 二.实现方法: 发布需 ...

  6. 【算法系列学习】[kuangbin带你飞]专题十二 基础DP1 G - 免费馅饼

    https://vjudge.net/contest/68966#problem/G 正解一: http://www.clanfei.com/2012/04/646.html #include< ...

  7. URL Scheme与openURL

    URL Schemes URL Schemes是苹果给出的用来跳转到系统应用或者跳转到别人的应用的一种机制.同时还可以在应用之间传数据. 设置一个URL Schemes:选中App工程->Inf ...

  8. C语言中的指针

    请先看C++中的指针概述,这里只是扩充 数组指针 其实这里主要说的就是c++中的指针运算 /* 数组元素指针: 一个变量有地址,一个数组包含若干个元素,每个数组元素都有相应的地址, 指针变量可以指向数 ...

  9. hdu 1254 推箱子(搜索)

    我写的第一道感觉比较难的搜索 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1254 首先要推箱子的话要满足人能够在箱子旁边,而且人的对面也是可通的. ...

  10. hdu1520 Anniversary party 简单树形DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 思路:树形DP的入门题 定义dp[root][1]表示以root为根节点的子树,且root本身参 ...