• UCloud 的安全秘钥


    UCloud 的安全秘钥(困难)

      •  1200ms
      •  262144K

    每个 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
    分析:看了题解发现原来可以集合hash,hash新姿势get,收获巨大,233
       同时不同的len值不超过sqrt(n)个,离线分组对每个len处理即可;

    代码:
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <bitset>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cassert>
    #include <ctime>
    #include<unordered_map>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define sys system("pause")
    const int maxn=1e5+10;
    const int N=5e2+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}
    int n,m,k,t,a[maxn],cnt[maxn],ret[maxn],tot;
    unsigned ll op[maxn],ha[maxn];
    vector<pair<int,unsigned ll> >qu[maxn];
    vi tmp;
    int main()
    {
        int i,j;
        rep(i,1,maxn-10)op[i]=(unsigned ll)rand()*rand();
        scanf("%d",&n);
        rep(i,1,n)scanf("%d",&a[i]);
        scanf("%d",&t);
        rep(i,1,t)
        {
            scanf("%d",&m);
            if(++cnt[m]==1&&m<=n)tmp.pb(m);
            unsigned ll now=0;
            rep(j,1,m)scanf("%d",&k),now+=op[k];
            if(m<=n)qu[m].pb(mp(i,now));
        }
        for(i=0;i<tmp.size();i++)
        {
            int now=tmp[i];
            tot=0;
            ha[0]=0;
            rep(j,1,now)ha[tot]+=op[a[j]];
            for(j=now+1;j<=n;j++)
            {
                ++tot;
                ha[tot]=ha[tot-1]+op[a[j]]-op[a[j-now]];
            }
            sort(ha,ha+tot+1);
            for(j=0;j<qu[now].size();j++)
            {
                ret[qu[now][j].fi]=upper_bound(ha,ha+tot+1,qu[now][j].se)-lower_bound(ha,ha+tot+1,qu[now][j].se);
            }
        }
        rep(i,1,t)printf("%d
    ",ret[i]);
        return 0;
    }
  • 相关阅读:
    机器学习的定义和分类
    选股
    mysql修改密码
    快速排序
    php的错误类型
    MySQL数据库优化
    库存超卖问题
    循环处理
    kafka安装配置
    JavaScript、jQuery杂记
  • 原文地址:https://www.cnblogs.com/dyzll/p/6938827.html
Copyright © 2020-2023  润新知