zoukankan      html  css  js  c++  java
  • 计蒜客第五场 UCloud 的安全秘钥(中等) (尺取游标法

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

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

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

    此时,我们就称 aa 和 bb 近似匹配,即 a approx bab。例如,(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(1leq s_ileq n)s1​​,s2​​,...,sn​​(1si​​n),表示 ss 串。

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

    接下来 mm 个部分:

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

    每个部分第二行包含 kk 个正整数 t_1,t_2,...,t_k(1leq t_ileq n)t1​​,t2​​,...,tk​​(1ti​​n),表示 TT 中的一个串 tt。

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

    对于简单版本:1leq n,mleq 1001n,m100;

    对于中等版本:1leq nleq 50000,1leq mleq 5001n50000,1m500;

    对于困难版本:1 le n le 50000, 1 le m le 1000001n50000,1m100000。

    输出格式

    输出 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

    对于每个询问
    实际上我们的想法是能通过类似尺取的方式,将每一个长度为len的区间取出来,能hash出来,O(1)查询hash值,从而做到查询O(n*m)
    实际上这个hash没想出来,但是这里有一种巧妙的尺取法,
    对于每个询问,我们记录下每种数字的个数,标记数组是这样一个东西
    (下面这个v数组就像游标一样,再加上我用了尺取法,所以就起名叫尺取游标法啦

    如果t串中1的个数比s的某一子串多那么v[1]>0

    如果比它少就小于零,|v[1]|代表相差元素个数

    我们记录一下t串中v[]不为零的个数cnt

    则当且仅当某串的各串数量和t串相等时,cnt为0

    简单考虑几种情况,某串种类比t多,cnt肯定会变大

    某串的种类比t少,cnt可能变大也可能变小,但不为0,具体要看每种的数量

    某串种类和t相等,但某类数字出现过多或过少,cnt不为0

    所以我们发现动态维护cnt是可行的

    区间滑动改变一个左端点,改变一个右端点,动态维护v数组,并且根据v修改cnt

    如果cnt为0一次,那么对答案的贡献加一

    #include <stdio.h>
    #include <cstring>
    #include <vector>
    #include <map>
    using namespace std;
    const int maxn=5e4+7;
    typedef long long ll;
    int s[maxn],t[maxn],ns,nt,m,v[maxn];
    int main(){
        scanf("%d",&ns);
        for(int i=0;i<ns;++i) scanf("%d",s+i);
        scanf("%d",&m);
        while(m--){
            scanf("%d",&nt);
            for(int i=0;i<nt;++i) scanf("%d",t+i);
            memset(v,0,sizeof(v));
            int cnt=0;
            for(int i=0;i<nt;++i){
                v[t[i]]++;
                if(v[t[i]]==1) cnt++;
            }
            for(int i=0;i<nt;++i){
                if(v[s[i]]==0) cnt++;
                else if(v[s[i]]==1) cnt--;
                v[s[i]]--;
            }
            int ans=0,l=1,r=nt;
            if(!cnt) ans++;
            while(r<ns){
                if(v[s[r]]==0) cnt++;
                else if(v[s[r]]==1) cnt--;
                v[s[r]]--;
                if(v[s[l-1]]==-1) cnt--;
                else if(v[s[l-1]]==0) cnt++;
                v[s[l-1]]++;
                if(!cnt) ans++;
                l++;r++;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    Android服务器——TomCat服务器的搭建
    Ubuntu16.04 Liunx下同时安装Anaconda2与Anaconda3
    android中代码操作外部SD卡出错:W/System.err(1595): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
    查准率与查全率(precision and recall) 的个人理解
    Python游戏-实现键盘控制功能
    UGUI世界坐标转换为UI本地坐标(游戏Hud的实现)
    LoadRunner中遭遇交互数据加密的处理方案
    [Java]链表的打印,反转与删除
    优化程序性能(3)——提高并行性
    基本排序算法的python实现
  • 原文地址:https://www.cnblogs.com/linkzijun/p/6940241.html
Copyright © 2011-2022 走看看