2017 计蒜之道 初赛 第五场 UCloud 的安全秘钥(中等)

每个 UCloud 用户会构造一个由数字序列组成的秘钥,用于对服务器进行各种操作。作为一家安全可信的云计算平台,秘钥的安全性至关重要。因此,UCloud 每年会对用户的秘钥进行安全性评估,具体的评估方法如下:

首先,定义两个由数字序列组成的秘钥 aa 和 bb近似匹配(\approx≈) 的关系。aa 和 bb 近似匹配当且仅当同时满足以下两个条件:

  • |a|=|b|∣a∣=∣b∣,即 aa 串和 bb 串长度相等。
  • 对于每种数字 cc,cc 在 aa 中出现的次数等于cc 在 bb 中出现的次数。

此时,我们就称 aa 和 bb 近似匹配,即 a \approx ba≈b。例如,(1,3,1,1,2)\approx(2,1,3,1,1)(1,3,1,1,2)≈(2,1,3,1,1)。

UCloud 每年会收集若干不安全秘钥,这些秘钥组成了不安全秘钥集合 TT。对于一个秘钥 ss 和集合 TT 中的秘钥 tt 来说,它们的相似值定义为:ss 的所有连续子串中与 tt 近似匹配的个数。相似值越高,说明秘钥 ss 越不安全。对于不安全秘钥集合 TT 中的每个秘钥 tt,你需要输出它和秘钥 ss 的相似值,用来对用户秘钥的安全性进行分析。

输入格式

第一行包含一个正整数 nn,表示 ss 串的长度。

第二行包含 nn 个正整数 s_1,s_2,...,s_n(1\leq s_i\leq n)s?1??,s?2??,...,s?n??(1≤s?i??≤n),表示 ss 串。

接下来一行包含一个正整数 mm,表示询问的个数。

接下来 mm 个部分:

每个部分第一行包含一个正整数 k(1\leq k\leq n)k(1≤k≤n),表示每个 tt 串的长度。

每个部分第二行包含 kk 个正整数 t_1,t_2,...,t_k(1\leq t_i\leq n)t?1??,t?2??,...,t?k??(1≤t?i??≤n),表示 TT 中的一个串 tt。

输入数据保证 TT 中所有串长度之和不超过 200000200000。

对于简单版本:1\leq n,m\leq 1001≤n,m≤100;

对于中等版本:1\leq n\leq 50000,1\leq m\leq 5001≤n≤50000,1≤m≤500;

对于困难版本:1 \le n \le 50000, 1 \le m \le 1000001≤n≤50000,1≤m≤100000。

输出格式

输出 mm 行,每行一个整数,即与 TT 中每个串 tt近似匹配的 ss 的子串数量。

样例解释

对于第一个询问,(3,2,1,3)\approx(2,3,1,3)(3,2,1,3)≈(2,3,1,3),(3,2,1,3)\approx(3,1,3,2)(3,2,1,3)≈(3,1,3,2);

对于第二个询问,(1,3)\approx(3,1)(1,3)≈(3,1),(1,3)\approx(1,3)(1,3)≈(1,3);

对于第三个询问,(3,2)\approx(2,3)(3,2)≈(2,3),(3,2)\approx(3,2)(3,2)≈(3,2)。

样例输入

5
2 3 1 3 2
3
4
3 2 1 3
2
1 3
2
3 2

样例输出

2
2
2
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=50000+10;
int a[maxn],b[maxn],n,m,nn;
int v1[maxn],v2[maxn];
int main()
{
    scanf("%d",&n);
    for(int i=0; i<n; i++)
        scanf("%d",a+i);
    scanf("%d",&nn);
    while(nn--)
    {
        scanf("%d",&m);
        if(m==1)
        {
            scanf("%d",b);
            int ans=0;
            for(int i=0; i<n; i++)
                if(a[i]==b[0]) ans++;
            printf("%d\n",ans);
            continue;
        }
        memset(v2,0,sizeof(v2));
        memset(v1,0,sizeof(v1));
        for(int i=0; i<m; i++)
        {
            scanf("%d",b+i);
            v2[b[i]]++;
        }
        int ans=0;
        int c=0;
        for(int j=0; j<m; j++)
            v1[a[j]]++;  

        for(int i=1; i<=n; i++)
            if(v1[i]!=v2[i]) c++;
        if(c==0) ans++;
        for(int i=1; i<=n-m; i++)
        {
            if(v1[a[i-1]]==v2[a[i-1]]) c++;
            if(v1[a[i+m-1]]==v2[a[i+m-1]]) c++;
            v1[a[i-1]]--;
            v1[a[i+m-1]]++;
            if(v1[a[i-1]]==v2[a[i-1]]) c--;
            if(v1[a[i+m-1]]==v2[a[i+m-1]]) c--;
            if(c==0) ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}  
时间: 2024-12-31 12:47:38

2017 计蒜之道 初赛 第五场 UCloud 的安全秘钥(中等)的相关文章

2017 计蒜之道 初赛 第五场 D. UCloud 的安全秘钥(困难)

小数据打表,大数据暴力. 导致超时的主要原因是$m$小的询问次数太多,可以把$m≤10$的答案直接暴力打表存起来,$m>10$的用$C$题的方法即可. #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <vector> #include <queue> #in

2017 计蒜之道 初赛 第五场 B. UCloud 的安全秘钥(简单)

暴力. 暴力枚举$S$串的每一个长度为$m$的子串,排序判断即可. #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #inc

2017 计蒜之道 初赛 第五场 C. UCloud 的安全秘钥(中等)

暴力. $O(m*n)$的算法可以通过此题,每次询问$O(m)$扫S数组,统计不同数字的个数,每次移动最多只会变化两个数字,如果不同数字个数为$0$,那么答案加$1$. #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <vector> #include <queue&g

2017 计蒜之道 初赛 第五场 A. UCloud 机房的网络搭建

贪心. 从大到小排序之后进行模拟,注意$n=1$和$n=0$的情况. #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #in

(哈希)计算之道初赛第五场 - UCloud 的安全秘钥

这种渣比代码也能A? 数据太水了吧.. 按长度统一起来算一次滑动窗口的哈希值,sort一下,二分算数量. 复杂度应该是sqrt(T)*n*logn吧. 自己出个数据都能卡掉. 1 #include <string> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <map> 7 #inclu

2018 计蒜之道 初赛 第五场

这次的比赛没有现场打,而是等到了今天才来补. 主要是因为那时候和HHHOJ上的比赛冲突了,所以就没写. 这次前三题的难度都比较低,但是就是一个T4要莫比乌斯反演.又是不可食用的. 好了我们开始看题. A. 贝壳找房搬家 这道题刚开始看的时候没看懂题意,觉得T1就是这种立体几何的题目,有种想死的感觉. 因为我认为这个方块可以不规则地想怎么放就怎么放的,其实题目中有一句话: 我们可以把这堆箱子看成一个\(x \times y \times z\) 的长方体. 什么?刚开始只能是长方体吗?好吧好像还是

2017 计蒜之道 初赛 第三场 D. 腾讯狼人杀 (点边都带权的最大密度子图)

点边都带权的最大密度子图,且会有必须选的点. 写到一半没保存实验室断电,气炸.明天补详细题解. #include<bits/stdc++.h> using namespace std; const double eps = 1e-7; const int INF = 0x3f3f3f3f; const int MAXN= 405;//点数的最大值 const int MAXM= 1e6 + 10;//边数的最大值 #define captype double struct Edge{ int

2017 计蒜之道 初赛 第一场 B.阿里天池的新任务

2017 计蒜之道 初赛 第一场 B.阿里天池的新任务 1 /* QYP kuai wo dai ma*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<iomanip> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cstdio> 8 #include<queue> 9 #include<ctime

2017计蒜之道 初赛 第二场 百度的科学计算器(简单)

/** 题目:2017计蒜之道 初赛 第二场 百度的科学计算器(简单) 链接:https://nanti.jisuanke.com/t/15504 题意:给一个合法的表达式,包含加号+.减号-.括号().数字常量,表达式中没有空格. 输入数据保证数字常量以及计算过程中数值绝对值均不超过 10^12??,对于浮点型数值常量,保证小数点后不超过 666 位. 思路:暴力模拟:python有函数可以直接调用. 坑点:如果表达式中出现过浮点数,那么输出结果保留6位小数, 否则输出整数,不出现小数. */