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. CF #345 Div1 D Zip-line

    题目链接:http://codeforces.com/contest/650/problem/D 大意是给一个数组,若干询问,每一次把一个数字改为另一个数字,问当前数组最长上升子序列,询问之间是独立的 ...

  2. wpf之StackPanel、WrapPanel、WrapPanel之间的关系

    一.StackPanel StackPanel是以堆叠的方式显示其中的控件 1.可以使用Orientation属性更改堆叠的顺序分为水平方向(Orientation="Horizontal& ...

  3. leetcode水题(一)

    Two Sum 1 public int[] twoSum(int[] numbers,int target){ Map<Integer,Integer> map = new HashMa ...

  4. Eclipse显示内存占用

  5. 在线恶意软件和URL分析集成框架 – MalSub

    malsub是一个基于Python 3.6.x的框架,它的设计遵循了当前最流行的互联网软件架构RESTful架构,并通过其RESTful API应用程序编程接口(API),封装了多个在线恶意软件和UR ...

  6. .Net Core Session使用

    Sessiong 添加程序集 Microsoft.AspNetCore.Session 在Startup.cs 的 ConfigureServices中添加Session中间件设置 // sessio ...

  7. 【山东省选2008】郁闷的小J 平衡树Treap

    小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的.具体说来,书架由N ...

  8. UVA 10905 Children's Game (贪心)

    Children's Game Problem Description There are lots of number games for children. These games are pre ...

  9. OC中的单例

    概念 单例模式的意图是类的对象称为系统中唯一的实例,提供一个访问点,供客户类共享资源 什么情况下使用单例 )类只能由一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法 )这个唯一的实例 ...

  10. Docker- 创建支持SSH服务的容器镜像

    示例 - CentOS7 [root@CentOS-7 ~]# cat ssh-centos7 FROM centos:centos7 MAINTAINER anliven "anliven ...